from dash import Dash, Input, Output, State import dash_bootstrap_components as dbc import pandas as pd from data.functions import * from transportEqs import * import numpy as np from Kps_function.read_Kps_model import * import os from figure import build_figure from main_layout import build_main_layout from instructions import build_instructions_layout from rst_info import build_rst_layout from dash import html, dcc app = Dash( __name__, assets_folder=os.path.join(os.path.dirname(__file__), "assets"), suppress_callback_exceptions=True, #external_stylesheets=[dbc.themes.BOOTSTRAP], ) # -------------------------------------------------------------------- # Layout # -------------------------------------------------------------------- app.layout = html.Div([ dcc.Location(id="url", refresh=False), html.Div(id="page-content") # <-- this MUST exist here ]) app.validation_layout = html.Div([ app.layout, build_main_layout(), build_instructions_layout(), build_rst_layout(), ]) @app.callback( Output("page-content", "children"), Input("url", "pathname") ) def route(pathname): if pathname == "/instructions": return build_instructions_layout() elif pathname == "/rst": return build_rst_layout() else: return build_main_layout() # -------------------------------------------------------------------- # Main callback # -------------------------------------------------------------------- @app.callback( Output("c1_solvent", "disabled"), Output("c1_volume", "disabled"), Output("c1_swelling", "disabled"), Output("c1_temp", "disabled"), Output("c1_iterations", "disabled"), Input("condition1_mode", "value"), State("c1_solvent", "value"), ) def toggle_condition1_inputs(mode, current_value): disable = (mode != "in_vitro") return disable, disable, disable, disable, disable @app.callback( Output("c2_solvent", "disabled"), Output("c2_volume", "disabled"), Output("c2_swelling", "disabled"), Output("c2_temp", "disabled"), Output("c2_iterations", "disabled"), Input("condition2_mode", "value"), State("c2_solvent", "value"), ) def toggle_condition2_inputs(mode, current_value): disable = (mode != "in_vitro") return disable, disable, disable, disable, disable @app.callback( Output("mm0_chart", "figure"), Input("calculate", "n_clicks"), State("matrix", "value"), State("tg", "value"), State("crystal", "value"), State("density", "value"), State("polymer_volume", "value"), State("surface_area", "value"), # Condition 1 State("condition1_mode", "value"), State("c1_solvent", "value"), State("c1_volume", "value"), State("c1_swelling", "value"), State("c1_temp", "value"), State("c1_time", "value"), State("c1_iterations", "value"), # Condition 2 State("condition2_mode", "value"), State("c2_solvent", "value"), State("c2_volume", "value"), State("c2_swelling", "value"), State("c2_temp", "value"), State("c2_time", "value"), State("c2_iterations", "value"), State("samples", "value"), prevent_initial_call=True, ) def update_chart(n_clicks, matrix, tg, crystal, density, polymer_volume, surface_area, c1_mode, c1_solvent, c1_volume, c1_swelling, c1_temp, c1_time, c1_iter, c2_mode, c2_solvent, c2_volume, c2_swelling, c2_temp, c2_time, c2_iter,samples): # TODO: replace with logic that uses the form inputs # For now, simply return the same figure when "Calculate" is clicked. df = pd.DataFrame() df['CASRN'] = soluteData['CASRN'].to_numpy() N = int(samples) pindex = np.where(polymers == matrix)[0][0] CHRIS_category = categories[pindex] Polymer_Density = float(density) Polymer_Tg = float(tg) + 273.15 Polymer_X = float(crystal)/100. L = float(polymer_volume)/float(surface_area) # Condition 1 ExtractionTime = float(c1_time) * 3600. if c1_mode == 'in_vivo_conservative': medians, lowers, uppers = ConservativeMonteCarlo(soluteData, CHRIS_category, L, ExtractionTime, N) elif c1_mode == 'in_vivo_tissue': medians, lowers, uppers = TissueMonteCarlo(soluteData, CHRIS_category, L, ExtractionTime, N) else: Solvent_Name = c1_solvent Solvent_MW = Solvent_MWs[Solvent_Name] Solvent_Density = Solvent_Densities[Solvent_Name] Solvent_PI = Solvent_PIs[Solvent_Name] ExtractionT = float(c1_temp) + 273.15 Ms_M0 = float(c1_swelling) Swell = 1.+(Ms_M0-1.)*Polymer_Density/Solvent_Density w = (Ms_M0 - 1.)/(Ms_M0-Polymer_X) Iterations = float(c1_iter) Lbath = float(c1_volume) / float(surface_area) medians, lowers, uppers = ExtractMonteCarlo(soluteData, Solvent_PI, w, ExtractionT, Polymer_Tg, Solvent_Name, Solvent_MW, ExtractionTime, Swell, Iterations, CHRIS_category, L, Lbath, N) df['Condition 1'] = medians df['Cond1_err_plus'] = uppers-medians df['Cond1_err_minus'] = medians-lowers # Condition 2 ExtractionTime = float(c2_time) * 3600. if c2_mode == 'in_vivo_conservative': medians, lowers, uppers = ConservativeMonteCarlo(soluteData, CHRIS_category, L, ExtractionTime, N) elif c2_mode == 'in_vivo_tissue': medians, lowers, uppers = TissueMonteCarlo(soluteData, CHRIS_category, L, ExtractionTime, N) else: Solvent_Name = c2_solvent Solvent_MW = Solvent_MWs[Solvent_Name] Solvent_Density = Solvent_Densities[Solvent_Name] Solvent_PI = Solvent_PIs[Solvent_Name] ExtractionT = float(c2_temp) + 273.15 Ms_M0 = float(c2_swelling) Swell = 1. + (Ms_M0 - 1.) * Polymer_Density / Solvent_Density w = (Ms_M0 - 1.) / (Ms_M0 - Polymer_X) Iterations = float(c2_iter) Lbath = float(c2_volume) / float(surface_area) medians, lowers, uppers = ExtractMonteCarlo(soluteData, Solvent_PI, w, ExtractionT, Polymer_Tg, Solvent_Name, Solvent_MW, ExtractionTime, Swell, Iterations, CHRIS_category, L, Lbath, N) df['Condition 2'] = medians df['Cond2_err_plus'] = uppers - medians df['Cond2_err_minus'] = medians - lowers fig = build_figure(df) return fig def ConservativeMonteCarlo(soluteData, CHRIS_category, L, time, N): nSolutes = len(soluteData) medians = zeros(nSolutes) lowers = zeros(nSolutes) uppers = zeros(nSolutes) for iSolute in range(nSolutes): Solute_MW = soluteData['MW_new'].iloc[iSolute] D_CHRIS = get_D_CHRIS(Solute_MW, CHRIS_category, N=N) tau = D_CHRIS * time / L ** 2. # fixed 1 day mass = Conservative(tau) medians[iSolute] = percentile(mass, 50) lowers[iSolute] = percentile(mass, 25) uppers[iSolute] = percentile(mass, 75) return medians, lowers, uppers def TissueMonteCarlo(soluteData, CHRIS_category, L, time, N): nSolutes = len(soluteData) medians = zeros(nSolutes) lowers = zeros(nSolutes) uppers = zeros(nSolutes) for iSolute in range(nSolutes): Solute_MW = soluteData['MW_new'].iloc[iSolute] Solute_logP = soluteData['LogP_new'].iloc[iSolute] D_CHRIS = get_D_CHRIS(Solute_MW, CHRIS_category, N=N) tau = D_CHRIS * time / L ** 2. Dt = get_Dt(N) Kpt = get_Kpt(Solute_logP, N) beta = (1. / Kpt) * sqrt(Dt / D_CHRIS) mass = SolubilityLimited(beta, tau) medians[iSolute] = percentile(mass, 50) lowers[iSolute] = percentile(mass, 25) uppers[iSolute] = percentile(mass, 75) return medians, lowers, uppers def ExtractMonteCarlo(soluteData, Solvent_PI, w, ExtractionT, Polymer_Tg, Solvent_Name, Solvent_MW, ExtractionTime, Swell, Iterations, CHRIS_category, L, Lbath, N): nSolutes = len(soluteData) medians = zeros(nSolutes) lowers = zeros(nSolutes) uppers = zeros(nSolutes) for iSolute in range(nSolutes): Solute_MW = soluteData['MW_new'].iloc[iSolute] Solute_logP = soluteData['LogP_new'].iloc[iSolute] Solute_Vabc = soluteData['Vabc'].iloc[iSolute] D_Extract = get_D_Extract(w, ExtractionT, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, Solute_Vabc, CHRIS_category, N=N) tau = D_Extract * ExtractionTime / L ** 2. ToKPS = array([[Solute_logP, Solvent_PI]]) model = QuantileGridFromCoeffs(export_dir='Kps_function/Kps_model') Kps = 10**model.sample(ToKPS, n_samples=N)[0] alpha = Lbath / L / Kps massExtraction = zeros(N) for i in range(N): massExtraction[i] = Extraction(tau[i], alpha[i], Kps[i], Swell, Iterations) medians[iSolute] = percentile(massExtraction, 50) lowers[iSolute] = percentile(massExtraction, 25) uppers[iSolute] = percentile(massExtraction, 75) return medians, lowers, uppers if __name__ == "__main__": app.run(debug=True)