from dash import html, dcc import dash_bootstrap_components as dbc from data.functions import * from figure import build_figure def build_main_layout() -> html.Div: 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) 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 html.Div( style={ "fontFamily": "Arial, Helvetica, sans-serif", "padding": "15px", }, children=[ html.H1("Extraction condition comparison tool", style={ "textAlign": "center", "marginBottom": "10px", "fontSize": "36px", }, ), html.Div( style={ "display": "flex", "gap": "40px", }, children=[ # LEFT: Form / Controls html.Div( style={ "flex": "0 0 40%", "maxWidth": "500px", }, children=[ # Polymer component section html.H3( "Polymer component", style={ "textDecoration": "underline", "fontSize": "18px", "marginBottom": "10px", }, ), html.Div( style={ "display": "grid", "gridTemplateColumns": "1fr 1fr", "columnGap": "20px", "rowGap": "10px", "marginBottom": "10px", }, children=[ # Left column html.Div( children=[ html.Div("Matrix"), dcc.Dropdown( id="matrix", options=[{"label": x, "value": x} for x in polymers], value=polymers[25], # default selection (optional) clearable=False, style={"width": "100%"} ), html.Div("Tg (°C)", style={"marginTop": "10px"}), dcc.Input( id="tg", type="number", placeholder="0.0", value="0.0", style={"width": "100%"}, required=True, ), html.Div( "Crystallinity (%)", style={"marginTop": "10px"}, ), dcc.Input( id="crystal", type="number", placeholder="0.0", value="0.0", style={"width": "100%"}, required=True, ), ] ), # Right column html.Div( children=[ html.Div("Density (g/cm³)"), dcc.Input( id="density", type="number", placeholder="1.0", value="1.0", style={"width": "100%"}, required=True, ), html.Div( "Volume (cm³)", style={"marginTop": "10px"}, ), dcc.Input( id="polymer_volume", type="number", placeholder="1.0", value="1.0", style={"width": "100%"}, required=True, ), html.Div( "Surface area (cm²)", style={"marginTop": "10px"}, ), dcc.Input( id="surface_area", type="number", placeholder="30.0", value="30.0", style={"width": "100%"}, required=True, ), ] ), ], ), # Conditions row html.Div( style={ "display": "grid", "gridTemplateColumns": "1fr 1fr", "columnGap": "30px", }, children=[ # Condition 1 html.Div( children=[ html.H3( "Condition #1", style={ "textDecoration": "underline", "fontSize": "18px", "marginBottom": "10px", }, ), html.Div( [ html.Div( dcc.RadioItems( id="condition1_mode", options=[ { "label": "In vitro", "value": "in_vitro", }, { "label": "In vivo (conservative)", "value": "in_vivo_conservative", }, { "label": "In vivo (tissue)", "value": "in_vivo_tissue", }, ], value="in_vitro", labelStyle={ "display": "inline-block" }, ), style={"marginBottom": "10px"}, ), ], ), html.Div("Solvent"), dcc.Dropdown( id="c1_solvent", options=[{"label": x, "value": x} for x in solvents], value=solvents[9], # default selection (optional) clearable=False, placeholder="", disabled=True, style={"width": "100%"} ), html.Div( "Volume (cm³)", style={"marginTop": "10px"}, ), dcc.Input( id="c1_volume", type="number", placeholder="10.0", value="10.0", style={"width": "100%"}, disabled=True, required=True, ), html.Div( "Swelling ratio (m/m)", style={"marginTop": "10px"}, ), dcc.Input( id="c1_swelling", type="number", placeholder="1.0", value="1.0", style={"width": "100%"}, disabled=True, required=True, ), html.Div( "Extraction T (°C)", style={"marginTop": "10px"}, ), dcc.Input( id="c1_temp", type="number", placeholder="50.0", value="50.0", style={"width": "100%"}, disabled=True, required=True, ), html.Div( "Extraction time (h)", style={"marginTop": "10px"}, ), dcc.Input( id="c1_time", type="number", placeholder="24.0", value="24.0", style={"width": "100%"}, #disabled=True, required=True, ), html.Div( "# of iterations", style={"marginTop": "10px"}, ), dcc.Input( id="c1_iterations", type="number", placeholder="1", value="1", style={"width": "100%"}, disabled=True, required=True, ), ] ), # Condition 2 html.Div( children=[ html.H3( "Condition #2", style={ "textDecoration": "underline", "fontSize": "18px", "marginBottom": "10px", }, ), html.Div( [ html.Div( dcc.RadioItems( id="condition2_mode", options=[ { "label": "In vitro", "value": "in_vitro", }, { "label": "In vivo (conservative)", "value": "in_vivo_conservative", }, { "label": "In vivo (tissue)", "value": "in_vivo_tissue", }, ], value="in_vivo_conservative", labelStyle={ "display": "inline-block" }, ), style={"marginBottom": "10px"}, ), ], ), html.Div("Solvent"), dcc.Dropdown( id="c2_solvent", options=[{"label": x, "value": x} for x in solvents], value=solvents[2], # default selection (optional) clearable=False, placeholder="", disabled=True, style={"width": "100%"} ), html.Div( "Volume (cm³)", style={"marginTop": "10px"}, ), dcc.Input( id="c2_volume", type="number", placeholder="10.0", value="10.0", style={"width": "100%"}, disabled=True, required=True, ), html.Div( "Swelling ratio (m/m)", style={"marginTop": "10px"}, ), dcc.Input( id="c2_swelling", type="number", placeholder="1.0", value="1.0", style={"width": "100%"}, disabled=True, required=True, ), html.Div( "Extraction T (°C)", style={"marginTop": "10px"}, ), dcc.Input( id="c2_temp", type="number", placeholder="50.0", value="50.0", style={"width": "100%"}, disabled=True, required=True, ), html.Div( "Extraction time (h)", style={"marginTop": "10px"}, ), dcc.Input( id="c2_time", type="number", placeholder="24.0", value="24.0", style={"width": "100%"}, #disabled=True, required=True, ), html.Div( "# of iterations", style={"marginTop": "10px"}, ), dcc.Input( id="c2_iterations", type="number", placeholder="1", value="1", style={"width": "100%"}, disabled=True, required=True, ), ] ), ], ), # Calculate button html.Div( style={ "marginTop": "10px", }, children=[ # ---- Header on its own line ---- html.H3( "Monte Carlo", style={ "textDecoration": "underline", "fontSize": "18px", "marginBottom": "15px", }, ), # ---- Two-column layout: Samples/Input | Calculate ---- html.Div( style={ "display": "grid", "gridTemplateColumns": "1fr 1fr", "columnGap": "20px", "marginTop": "10px", }, children=[ # -------- Column 1: Samples label + input -------- html.Div( style={"display": "flex", "flexDirection": "column", }, children=[ html.Div("Samples"), dcc.Input( id="samples", type="number", placeholder="1000", value="1000", required=True, ), ], ), # -------- Column 2: Calculate button -------- html.Div( style={"textAlign": "center"}, children=[ html.Button( "Calculate", id="calculate", n_clicks=0, style={ "padding": "8px 25px", "border": "1px solid #333", "borderRadius": "3px", "backgroundColor": "white", "cursor": "pointer", }, ) ], ), ], ), ], ) ], ), # RIGHT: Bar Chart html.Div( style={ "flex": "1", "display": "flex", "flexDirection": "column", # <-- key change "justifyContent": "center", }, children=[ dcc.Loading( id="mm0_loading", type="default", # still works with custom_spinner # This box defines the exact area of the graph and overlay parent_style={ "position": "relative", "width": "800px", # match figure layout.width "height": "600px", # match figure layout.height }, # This is the semi-transparent veil over that 600x800 box overlay_style={ "backgroundColor": "rgba(255, 255, 255, 0.5)", "display": "flex", "justifyContent": "center", "alignItems": "center", }, custom_spinner=html.Div( [ html.H2("Processing"), dbc.Spinner(color="danger"), ], style={"textAlign": "center"}, ), children=dcc.Graph( id="mm0_chart", figure=placeholder_fig, config={"displayModeBar": False}, # Graph fills the 600x800 parent style={ "width": "800px", "height": "600px", }, ), ), html.Div( 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"), # ", and for reference and disclaimer information, please see the ", # dcc.Link("RST information page", href="/rst"), ".", ], style={ "maxWidth": "800px", "margin": "1.25rem auto 2rem auto", "lineHeight": "1.4", "color": "#555", } ), style={"width": "800px"}, ), ], ), ], ), ], )