Spaces:
Sleeping
Sleeping
Download main_layout.py from osel-dbcms/Justify: direct link, hf CLI and curl.
- Browser
- Download file 16.6 kB
-
https://huggingface.co/spaces/osel-dbcms/Justify/resolve/main/main_layout.py
- Command line
-
hf download hf://spaces/osel-dbcms/Justify/main_layout.py
-
curl -L -o main_layout.py https://huggingface.co/spaces/osel-dbcms/Justify/resolve/main/main_layout.py
16.6 kB
| from dash import html, dcc | |
| import pandas as pd | |
| import numpy as np | |
| from data.functions import * | |
| from figure import build_figure | |
| import plotly.graph_objects as go | |
| # ============================================================ | |
| # Small reusable layout helpers | |
| # ============================================================ | |
| FULL_WIDTH_STYLE = {"width": "100%"} | |
| FIELD_LABEL_STYLE = {"marginTop": "4px"} | |
| def section_header(text): | |
| """Standard section heading.""" | |
| return html.H3(text, className="section-header") | |
| def field_label(text, first=False): | |
| """Standard input label.""" | |
| if first: | |
| return html.Div(text) | |
| return html.Div(text, style=FIELD_LABEL_STYLE) | |
| def numeric_input( | |
| component_id, | |
| value, | |
| placeholder=None, | |
| disabled=False, | |
| ): | |
| """Standard full-width numeric input.""" | |
| if placeholder is None: | |
| placeholder = str(value) | |
| return dcc.Input( | |
| id=component_id, | |
| type="number", | |
| placeholder=placeholder, | |
| value=value, | |
| style=FULL_WIDTH_STYLE, | |
| disabled=disabled, | |
| required=True, | |
| ) | |
| # ============================================================ | |
| # Placeholder figure | |
| # ============================================================ | |
| def build_placeholder_figure(): | |
| n = len(soluteData) | |
| df0 = pd.DataFrame( | |
| { | |
| "CASRN": soluteData["CASRN"].to_numpy(), | |
| "Condition 1": np.zeros(n), | |
| "Cond1_err_plus": np.zeros(n), | |
| "Cond1_err_minus": np.zeros(n), | |
| "Condition 2": np.zeros(n), | |
| "Cond2_err_plus": np.zeros(n), | |
| "Cond2_err_minus": np.zeros(n), | |
| } | |
| ) | |
| placeholder_fig = build_figure(df0) | |
| # Keep the CAS axis layout, but hide the placeholder bar traces. | |
| placeholder_fig.update_traces( | |
| opacity=0, | |
| hoverinfo="skip", | |
| showlegend=False, | |
| ) | |
| placeholder_fig.update_yaxes( | |
| range=[-2, 0] | |
| ) | |
| placeholder_fig.add_annotation( | |
| text="Click 'Calculate' to run model", | |
| xref="paper", | |
| yref="paper", | |
| x=0.5, | |
| y=0.5, | |
| showarrow=False, | |
| font=dict( | |
| size=22, | |
| color="gray", | |
| ), | |
| align="center", | |
| ) | |
| return placeholder_fig | |
| # ============================================================ | |
| # Polymer section | |
| # ============================================================ | |
| def build_polymer_section(): | |
| return html.Div( | |
| className="polymer-section", | |
| children=[ | |
| section_header("Polymer component"), | |
| html.Div( | |
| className="fields-grid", | |
| children=[ | |
| # Left column | |
| html.Div( | |
| children=[ | |
| field_label("Matrix", first=True), | |
| dcc.Dropdown( | |
| id="matrix", | |
| options=[ | |
| {"label": x, "value": x} | |
| for x in polymers | |
| ], | |
| value=polymers[25], | |
| clearable=False, | |
| style=FULL_WIDTH_STYLE, | |
| ), | |
| field_label("Tg (°C)"), | |
| numeric_input( | |
| component_id="tg", | |
| value="0.0", | |
| placeholder="0.0", | |
| ), | |
| field_label("Crystallinity (%)"), | |
| numeric_input( | |
| component_id="crystal", | |
| value="0.0", | |
| placeholder="0.0", | |
| ), | |
| ] | |
| ), | |
| # Right column | |
| html.Div( | |
| children=[ | |
| field_label("Density (g/cm³)", first=True), | |
| numeric_input( | |
| component_id="density", | |
| value="1.0", | |
| placeholder="1.0", | |
| ), | |
| field_label("Volume (cm³)"), | |
| numeric_input( | |
| component_id="polymer_volume", | |
| value="1.0", | |
| placeholder="1.0", | |
| ), | |
| field_label("Surface area (cm²)"), | |
| numeric_input( | |
| component_id="surface_area", | |
| value="30.0", | |
| placeholder="30.0", | |
| ), | |
| ] | |
| ), | |
| ], | |
| ), | |
| ] | |
| ) | |
| # ============================================================ | |
| # Solute section | |
| # ============================================================ | |
| def build_solute_section(): | |
| return html.Div( | |
| children=[ | |
| section_header("Solutes"), | |
| dcc.RadioItems( | |
| id="solute_source", | |
| options=[ | |
| { | |
| "label": "Default boundary chemicals", | |
| "value": "default", | |
| }, | |
| { | |
| "label": "User-defined chemicals", | |
| "value": "upload", | |
| }, | |
| ], | |
| value="default", | |
| inline=True, | |
| labelStyle={"marginRight": "15px"}, | |
| ), | |
| # Hidden unless "User-defined chemicals" is selected. | |
| html.Div( | |
| id="solute_upload_container", | |
| children=[ | |
| dcc.Upload( | |
| id="solute_upload", | |
| children=html.Div( | |
| [ | |
| "Drag and drop or ", | |
| html.A("select an Excel file"), | |
| ] | |
| ), | |
| accept=".xlsx,.xls", | |
| multiple=False, | |
| style={ | |
| "width": "100%", | |
| "height": "55px", | |
| "lineHeight": "55px", | |
| "borderWidth": "1px", | |
| "borderStyle": "dashed", | |
| "borderRadius": "4px", | |
| "textAlign": "center", | |
| "marginTop": "10px", | |
| }, | |
| ), | |
| html.Div( | |
| id="solute_upload_status", | |
| style={ | |
| "marginTop": "5px", | |
| "fontSize": "13px", | |
| }, | |
| ), | |
| html.Div( | |
| id="solute_calculate_warning", | |
| style={ | |
| "marginTop": "6px", | |
| "fontSize": "13px", | |
| "color": "firebrick", | |
| "fontWeight": "bold", | |
| }, | |
| ), | |
| ], | |
| style={"display": "none"}, | |
| ), | |
| dcc.Store(id="uploaded_solute_data"), | |
| ] | |
| ) | |
| # ============================================================ | |
| # Condition controls | |
| # ============================================================ | |
| def build_condition_column( | |
| number, | |
| default_mode, | |
| default_solvent, | |
| ): | |
| """ | |
| Build either Condition #1 or Condition #2. | |
| IDs are generated automatically: | |
| c1_solvent, c1_volume, ... | |
| c2_solvent, c2_volume, ... | |
| """ | |
| prefix = f"c{number}" | |
| return html.Div( | |
| children=[ | |
| html.H3( | |
| f"Condition #{number}", | |
| className="section-header", | |
| ), | |
| html.Div( | |
| style={"marginBottom": "10px"}, | |
| children=[ | |
| dcc.RadioItems( | |
| id=f"condition{number}_mode", | |
| options=[ | |
| { | |
| "label": "In vitro", | |
| "value": "in_vitro", | |
| }, | |
| { | |
| "label": "In vivo (conservative)", | |
| "value": "in_vivo_conservative", | |
| }, | |
| { | |
| "label": "In vivo (representative tissue)", | |
| "value": "in_vivo_tissue", | |
| }, | |
| ], | |
| value=default_mode, | |
| inline=False, | |
| labelStyle={ | |
| "display": "block", | |
| "marginBottom": "2px", | |
| }, | |
| ), | |
| ], | |
| ), | |
| field_label("Solvent", first=True), | |
| dcc.Dropdown( | |
| id=f"{prefix}_solvent", | |
| options=[ | |
| {"label": x, "value": x} | |
| for x in solvents | |
| ], | |
| value=default_solvent, | |
| clearable=False, | |
| placeholder="", | |
| disabled=True, | |
| style=FULL_WIDTH_STYLE, | |
| ), | |
| field_label("Volume (cm³)"), | |
| numeric_input( | |
| component_id=f"{prefix}_volume", | |
| value="10.0", | |
| placeholder="10.0", | |
| disabled=True, | |
| ), | |
| field_label("Swelling ratio (m/m)"), | |
| numeric_input( | |
| component_id=f"{prefix}_swelling", | |
| value="1.0", | |
| placeholder="1.0", | |
| disabled=True, | |
| ), | |
| field_label("Extraction T (°C)"), | |
| numeric_input( | |
| component_id=f"{prefix}_temp", | |
| value="50.0", | |
| placeholder="50.0", | |
| disabled=True, | |
| ), | |
| field_label("Extraction time (h)"), | |
| numeric_input( | |
| component_id=f"{prefix}_time", | |
| value="24.0", | |
| placeholder="24.0", | |
| disabled=False, | |
| ), | |
| field_label("# of iterations"), | |
| numeric_input( | |
| component_id=f"{prefix}_iterations", | |
| value="1", | |
| placeholder="1", | |
| disabled=True, | |
| ), | |
| ] | |
| ) | |
| def build_conditions_section(): | |
| return html.Div( | |
| className="conditions-grid", | |
| children=[ | |
| build_condition_column( | |
| number=1, | |
| default_mode="in_vitro", | |
| default_solvent=solvents[9], | |
| ), | |
| build_condition_column( | |
| number=2, | |
| default_mode="in_vivo_conservative", | |
| default_solvent=solvents[2], | |
| ), | |
| ], | |
| ) | |
| # ============================================================ | |
| # Monte Carlo section | |
| # ============================================================ | |
| def build_monte_carlo_section(): | |
| return html.Div( | |
| children=[ | |
| section_header("Monte Carlo"), | |
| html.Div( | |
| className="fields-grid", | |
| children=[ | |
| html.Div( | |
| children=[ | |
| html.Div("Samples"), | |
| numeric_input( | |
| component_id="samples", | |
| value="1000", | |
| placeholder="1000", | |
| ), | |
| ] | |
| ), | |
| html.Div( | |
| children=[ | |
| html.Div("Comparison quantity"), | |
| dcc.RadioItems( | |
| id="mc_option", | |
| options=[ | |
| { | |
| "label": "absolute", | |
| "value": "absolute", | |
| }, | |
| { | |
| "label": "ratio", | |
| "value": "ratio", | |
| }, | |
| ], | |
| value="absolute", | |
| inline=True, | |
| labelStyle={"marginRight": "15px"}, | |
| ), | |
| ] | |
| ), | |
| ], | |
| ), | |
| html.Div( | |
| className="calculate-row", | |
| children=[ | |
| html.Button( | |
| "Calculate", | |
| id="calculate", | |
| n_clicks=0, | |
| ) | |
| ], | |
| ), | |
| ] | |
| ) | |
| # ============================================================ | |
| # Results / graph panel | |
| # ============================================================ | |
| def build_results_panel(placeholder_fig): | |
| return html.Div( | |
| className="results-panel", | |
| style={ | |
| "flex": "1", | |
| "minWidth": 0, | |
| "boxSizing": "border-box", | |
| "border": "1px solid #D5DADF", | |
| "borderRadius": "4px", | |
| "backgroundColor": "#FFFFFF", | |
| "padding": "16px", | |
| "paddingTop": "12px", | |
| }, | |
| children=[ | |
| section_header("Results"), | |
| dcc.Loading( | |
| id="mm0_loading", | |
| type="default", | |
| color="#D60036", | |
| parent_style={ | |
| "position": "relative", | |
| "width": "100%", | |
| "minWidth": 0, | |
| }, | |
| children=dcc.Graph( | |
| id="mm0_chart", | |
| figure=placeholder_fig, | |
| responsive=True, | |
| config={"displayModeBar": False}, | |
| style={ | |
| "width": "100%", | |
| "height": "600px", | |
| }, | |
| ), | |
| ), | |
| html.P( | |
| [ | |
| "This tool provides an interface to " | |
| "physics-based models that can assist " | |
| "in selecting extraction conditions. ", | |
| "It enables comparison of predicted " | |
| "fractional release across in vitro " | |
| "and in vivo scenarios. ", | |
| "For additional information, please " | |
| "refer to the ", | |
| dcc.Link("quick start guide", href="/instructions"), | |
| ".", | |
| ], | |
| style={ | |
| "margin": "1.25rem 0 0", | |
| "lineHeight": "1.4", | |
| "color": "#555", | |
| }, | |
| ), | |
| ], | |
| ) | |
| # ============================================================ | |
| # Left-side control panel | |
| # ============================================================ | |
| def build_controls_panel(): | |
| return html.Section( | |
| className="controls-panel", | |
| **{"aria-label": "Model inputs"}, | |
| children=[ | |
| build_polymer_section(), | |
| build_solute_section(), | |
| build_conditions_section(), | |
| build_monte_carlo_section(), | |
| ], | |
| ) | |
| # ============================================================ | |
| # Main layout | |
| # ============================================================ | |
| def build_main_layout() -> html.Div: | |
| placeholder_fig = build_placeholder_figure() | |
| return html.Div( | |
| className="model-page", | |
| children=[ | |
| html.H1( | |
| "Extraction condition comparison tool", | |
| className="visually-hidden", | |
| ), | |
| html.Div( | |
| className="model-grid", | |
| children=[ | |
| build_controls_panel(), | |
| build_results_panel(placeholder_fig), | |
| ], | |
| ), | |
| ], | |
| ) |