Robert Elder commited on
Commit ·
e02ea72
1
Parent(s): 6b54e05
updated quantity module to use category-based sampling where possible
Browse files- data/db-polymer-properties-and-categories.xlsx +3 -0
- qrf/functions.py +1 -1
- quantity_module/functions.py +73 -8
- quantity_module/quantity.py +31 -24
data/db-polymer-properties-and-categories.xlsx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4e2cd733617280ef264e2fdc16cfbe97680d7f2b48655c19127b18f9295fd56c
|
| 3 |
+
size 25960
|
qrf/functions.py
CHANGED
|
@@ -51,6 +51,7 @@ def QRF_Ceramic(density, polytg, quantiles=[0.03,0.5,0.97], T=37, worstcase='hi'
|
|
| 51 |
|
| 52 |
|
| 53 |
def QRF_Apply(density, polytg, smiles, quantiles=[0.03,0.5,0.97], T=37):
|
|
|
|
| 54 |
nearest_T = QRF_T_list[np.abs(T-QRF_T_list).argmin()]
|
| 55 |
with open(f'qrf/qrf_model_bundle_{int(nearest_T)}.pkl','rb') as f:
|
| 56 |
reg, imp, scaler_X, sub_desc_list = pickle.load(f)
|
|
@@ -123,4 +124,3 @@ def QRF_DomainExtrap(estimator, X_train, X_test, D=0.0, return_features=False):
|
|
| 123 |
return dij, dij_feats
|
| 124 |
else:
|
| 125 |
return dij
|
| 126 |
-
|
|
|
|
| 51 |
|
| 52 |
|
| 53 |
def QRF_Apply(density, polytg, smiles, quantiles=[0.03,0.5,0.97], T=37):
|
| 54 |
+
"""T and Tg in C"""
|
| 55 |
nearest_T = QRF_T_list[np.abs(T-QRF_T_list).argmin()]
|
| 56 |
with open(f'qrf/qrf_model_bundle_{int(nearest_T)}.pkl','rb') as f:
|
| 57 |
reg, imp, scaler_X, sub_desc_list = pickle.load(f)
|
|
|
|
| 124 |
return dij, dij_feats
|
| 125 |
else:
|
| 126 |
return dij
|
|
|
quantity_module/functions.py
CHANGED
|
@@ -27,7 +27,7 @@ T_cut = 20
|
|
| 27 |
MW_cut = 20
|
| 28 |
|
| 29 |
use_new = True
|
| 30 |
-
T_cut_new = 0.5
|
| 31 |
|
| 32 |
#### read data files
|
| 33 |
# CHRIS parameter distributions
|
|
@@ -67,7 +67,7 @@ else:
|
|
| 67 |
# add volumes
|
| 68 |
df_final = pd.merge(df_final, df_desc[['Solute_InChIKey', 'Vabc', 'VMcGowan']], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
|
| 69 |
|
| 70 |
-
#### solvent-specific viscosity
|
| 71 |
# add MW
|
| 72 |
mws = []
|
| 73 |
for solv in df_visc['Solvent_Name']:
|
|
@@ -146,7 +146,8 @@ else:
|
|
| 146 |
df_final[f'D_WC_{solv}'] = D_WC
|
| 147 |
df_final[f'MW_solvent_{solv}'] = MW_solvent
|
| 148 |
|
| 149 |
-
def get_V(
|
|
|
|
| 150 |
calc = mordred.Calculator([mordred.descriptors.VdwVolumeABC, mordred.descriptors.McGowanVolume])
|
| 151 |
Vabc,Vmcg = list(calc(mol).values())
|
| 152 |
if not isinstance(Vabc, numbers.Number):
|
|
@@ -158,10 +159,10 @@ df_vd_solv = pd.read_excel('quantity_module/data/vrentas-duda-params.xlsx', shee
|
|
| 158 |
df_vd_solv.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
|
| 159 |
df_vd_poly = pd.read_excel('quantity_module/data/vrentas-duda-params.xlsx', sheet_name='Polymers')
|
| 160 |
df_vd_poly.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
|
| 166 |
## Calculate c
|
| 167 |
dfs_vd_allT = []
|
|
@@ -191,6 +192,14 @@ def get_c_dist(T,Tg,MW):
|
|
| 191 |
cs = cs[cs>0]
|
| 192 |
return cs
|
| 193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
def get_D_dists(w,T,Polymer_Tg,Solvent_Name,Solvent_MW,Solute_MW,CHRIS_category,rng,N=100000,return_DCs=False,input_Ds=None):
|
| 195 |
"""
|
| 196 |
D_dist_noswell, D_dist_swell, (c, Ds, DWCs, DCs) = get_D_dists(Swelling_wtfrac,T,Polymer_Tg,Solvent_Name,Solvent_MW,Solute_MW,CHRIS_category,return_DCs=True,N=N)
|
|
@@ -261,6 +270,63 @@ def get_D_dists(w,T,Polymer_Tg,Solvent_Name,Solvent_MW,Solute_MW,CHRIS_category,
|
|
| 261 |
else:
|
| 262 |
return D_dist_noswell, D_dist_swell
|
| 263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
def PlaneSheetFiniteBathMass(M0,D,K,PolymerVolume,SurfaceArea,SolventVolume,ExtractionTime,nterms,Qv=1):
|
| 265 |
### works with scalar- or vector-valued M0 and D
|
| 266 |
L = PolymerVolume/SurfaceArea #effective length scale of the component
|
|
@@ -311,4 +377,3 @@ def get_M_dist(D_dist, M_expt, PolymerVolume, SurfaceArea, SolventVolume, Extrac
|
|
| 311 |
M_M0 = PlaneSheetAnalytical(1.0, D_dist, K_expt, PolymerVolume, SurfaceArea, SolventVolume, ExtractionTime, nterms=5, Qv=Qv) # much faster and indistinguishable distribution from Mfunc_film
|
| 312 |
M0_pred = M_expt/M_M0
|
| 313 |
return M0_pred
|
| 314 |
-
|
|
|
|
| 27 |
MW_cut = 20
|
| 28 |
|
| 29 |
use_new = True
|
| 30 |
+
T_cut_new = 0.5
|
| 31 |
|
| 32 |
#### read data files
|
| 33 |
# CHRIS parameter distributions
|
|
|
|
| 67 |
# add volumes
|
| 68 |
df_final = pd.merge(df_final, df_desc[['Solute_InChIKey', 'Vabc', 'VMcGowan']], how='left', on='Solute_InChIKey', suffixes=('', '_dupe'))
|
| 69 |
|
| 70 |
+
#### solvent-specific viscosity
|
| 71 |
# add MW
|
| 72 |
mws = []
|
| 73 |
for solv in df_visc['Solvent_Name']:
|
|
|
|
| 146 |
df_final[f'D_WC_{solv}'] = D_WC
|
| 147 |
df_final[f'MW_solvent_{solv}'] = MW_solvent
|
| 148 |
|
| 149 |
+
def get_V(smiles):
|
| 150 |
+
mol = Chem.MolFromSmiles(smiles)
|
| 151 |
calc = mordred.Calculator([mordred.descriptors.VdwVolumeABC, mordred.descriptors.McGowanVolume])
|
| 152 |
Vabc,Vmcg = list(calc(mol).values())
|
| 153 |
if not isinstance(Vabc, numbers.Number):
|
|
|
|
| 159 |
df_vd_solv.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
|
| 160 |
df_vd_poly = pd.read_excel('quantity_module/data/vrentas-duda-params.xlsx', sheet_name='Polymers')
|
| 161 |
df_vd_poly.drop_duplicates(keep='first', inplace=True, ignore_index=True) # drop exact duplicates
|
| 162 |
+
df_props = pd.read_excel('data/db-polymer-properties-and-categories.xlsx')
|
| 163 |
+
df_vd_poly = pd.merge(df_vd_poly, df_props[['Polymer_Name','Polymer_Tg','Polymer_Tm', 'CHRIS Class', 'New Class']], how='left', on='Polymer_Name')
|
| 164 |
+
df_vd_poly['New Class'] = df_vd_poly['New Class'].fillna('none')
|
| 165 |
+
df_vd_poly['CHRIS Class'] = df_vd_poly['CHRIS Class'].fillna('none')
|
| 166 |
|
| 167 |
## Calculate c
|
| 168 |
dfs_vd_allT = []
|
|
|
|
| 192 |
cs = cs[cs>0]
|
| 193 |
return cs
|
| 194 |
|
| 195 |
+
def get_c_dist_cat(T,CHRIS_category,MW):
|
| 196 |
+
m = (~pd.isna(df_vd_allT['c'])) & (df_vd_allT['T-Tg']>0) & (np.abs(df_vd_allT['T']-T)<T_cut) & (np.abs(df_vd_allT['M1']-MW)<MW_cut) & (df_vd_allT['New Class']==CHRIS_category)
|
| 197 |
+
cs = df_vd_allT.loc[m, 'c']
|
| 198 |
+
cs = np.array(cs)
|
| 199 |
+
cs = cs[~np.isnan(cs)]
|
| 200 |
+
cs = cs[cs>0]
|
| 201 |
+
return cs
|
| 202 |
+
|
| 203 |
def get_D_dists(w,T,Polymer_Tg,Solvent_Name,Solvent_MW,Solute_MW,CHRIS_category,rng,N=100000,return_DCs=False,input_Ds=None):
|
| 204 |
"""
|
| 205 |
D_dist_noswell, D_dist_swell, (c, Ds, DWCs, DCs) = get_D_dists(Swelling_wtfrac,T,Polymer_Tg,Solvent_Name,Solvent_MW,Solute_MW,CHRIS_category,return_DCs=True,N=N)
|
|
|
|
| 270 |
else:
|
| 271 |
return D_dist_noswell, D_dist_swell
|
| 272 |
|
| 273 |
+
def get_D_dists_new(w,T,Polymer_Tg,Solvent_Name,Solvent_MW,Solute_MW,Solute_Vabc,CHRIS_category,rng,N=10000,return_DCs=False,input_Ds=None):
|
| 274 |
+
"""
|
| 275 |
+
D_dist_noswell, D_dist_swell = get_D_dists_new(w, 323.15, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, None, CHRIS_category, rng, return_DCs=False, N=int(1e5), input_Ds=diff)
|
| 276 |
+
"""
|
| 277 |
+
df_final_T = df_final.loc[np.abs(df_final['T']-T)<T_cut_new]
|
| 278 |
+
if (T <= Polymer_Tg) or (input_Ds is not None):
|
| 279 |
+
cs = get_c_dist(T,Polymer_Tg,Solvent_MW)
|
| 280 |
+
else:
|
| 281 |
+
cs = get_c_dist_cat(T,CHRIS_category,Solvent_MW)
|
| 282 |
+
if not len(cs):
|
| 283 |
+
cs = get_c_dist(T,Polymer_Tg,Solvent_MW)
|
| 284 |
+
c = rng.choice(cs, N)
|
| 285 |
+
if Solute_Vabc is None:
|
| 286 |
+
if Solute_MW < 50:
|
| 287 |
+
m50 = df_final_T['MW']<=50
|
| 288 |
+
else:
|
| 289 |
+
m50 = df_final_T['MW']>50
|
| 290 |
+
## within cutoffs, with at least N closest (by sorting, separating at MW = 50)
|
| 291 |
+
m2 = (np.abs(df_final_T['Polymer_Tg']-Polymer_Tg)<T_cut) & (np.abs(df_final_T['MW']-Solute_MW)<MW_cut) & m50
|
| 292 |
+
if m2.sum()<25:
|
| 293 |
+
vT = df_final_T.loc[m50,'Polymer_Tg']-Polymer_Tg; vM = df_final_T.loc[m50,'MW']-Solute_MW; m3 = pd.concat([np.abs(vT), np.abs(vM)], axis=1).sort_values(by=['Polymer_Tg', 'MW']).index[1:26]
|
| 294 |
+
m2 = list(set(m2.index[m2]).union(set(m3)))
|
| 295 |
+
if return_DCs:
|
| 296 |
+
Ds,DWCs,DCs = rng.choice([df_final_T.loc[m2,'D'], df_final_T.loc[m2,f'D_WC_{Solvent_Name}'], df_final_T.loc[m2,f'D_CHRIS_q50']], N, axis=1)
|
| 297 |
+
else:
|
| 298 |
+
Ds,DWCs = rng.choice([df_final_T.loc[m2,'D'], df_final_T.loc[m2,f'D_WC_{Solvent_Name}']], N, axis=1)
|
| 299 |
+
else:
|
| 300 |
+
DWCs, eta, MW_solvent = get_WC(T, Solvent_Name, Solute_Vabc)
|
| 301 |
+
## distribution of D_CHRIS
|
| 302 |
+
if input_Ds is None:
|
| 303 |
+
if Solute_MW > 50:
|
| 304 |
+
subkey = f'{CHRIS_category}_hi'
|
| 305 |
+
else:
|
| 306 |
+
subkey = f'{CHRIS_category}_lo'
|
| 307 |
+
allparams = [param_dists[Ti][subkey] for Ti in param_dists if T+T_cut_new >= int(Ti)+273.15 >= T-T_cut_new]
|
| 308 |
+
D_list = []
|
| 309 |
+
for params in allparams:
|
| 310 |
+
if params[0] == 'pir':
|
| 311 |
+
A_list = params[1:]
|
| 312 |
+
D_list += [Piringer(Solute_MW, Ai, T) for Ai in A_list]
|
| 313 |
+
else:
|
| 314 |
+
Ball = params[1]
|
| 315 |
+
A_list = params[2:]
|
| 316 |
+
D_list += [PowerLaw(Solute_MW, Ai, Ball) for Ai in A_list]
|
| 317 |
+
else:
|
| 318 |
+
D_list = input_Ds
|
| 319 |
+
D_dist_noswell = rng.choice(D_list, N)
|
| 320 |
+
if Solute_Vabc is None:
|
| 321 |
+
lnD_D0 = c*w/(1+(c-1)*w) * np.log(DWCs/Ds)
|
| 322 |
+
else:
|
| 323 |
+
lnD_D0 = c*w/(1+(c-1)*w) * np.log(DWCs/D_dist_noswell)
|
| 324 |
+
D_dist_swell = np.exp(np.log(D_dist_noswell)+lnD_D0)
|
| 325 |
+
if return_DCs:
|
| 326 |
+
return D_dist_noswell, D_dist_swell, (c, Ds, DWCs, DCs)
|
| 327 |
+
else:
|
| 328 |
+
return D_dist_noswell, D_dist_swell
|
| 329 |
+
|
| 330 |
def PlaneSheetFiniteBathMass(M0,D,K,PolymerVolume,SurfaceArea,SolventVolume,ExtractionTime,nterms,Qv=1):
|
| 331 |
### works with scalar- or vector-valued M0 and D
|
| 332 |
L = PolymerVolume/SurfaceArea #effective length scale of the component
|
|
|
|
| 377 |
M_M0 = PlaneSheetAnalytical(1.0, D_dist, K_expt, PolymerVolume, SurfaceArea, SolventVolume, ExtractionTime, nterms=5, Qv=Qv) # much faster and indistinguishable distribution from Mfunc_film
|
| 378 |
M0_pred = M_expt/M_M0
|
| 379 |
return M0_pred
|
|
|
quantity_module/quantity.py
CHANGED
|
@@ -35,7 +35,7 @@ def exposure():
|
|
| 35 |
def exp_post():
|
| 36 |
|
| 37 |
Polymer_Tg = float(request.form['Polymer_Tg']) ## NOTE Tg is provided in C
|
| 38 |
-
T = float(request.form['T'])
|
| 39 |
Polymer_Tg += 273.15
|
| 40 |
T += 273.15
|
| 41 |
rng = np.random.Generator(np.random.PCG64(seed=12345))
|
|
@@ -49,7 +49,7 @@ def exp_post():
|
|
| 49 |
|
| 50 |
if debug:
|
| 51 |
iupac, cas, smiles, MW, LogP, LogP_origin, rho, rho_origin, mp, mp_origin, molImage, error = ResolveChemical(chemName, IDtype, debug=debug, get_properties=['logp','rho','mp'])
|
| 52 |
-
LogP_origin, rho_origin, mp_origin = f' ({LogP_origin})', f' ({rho_origin})', f' ({mp_origin})',
|
| 53 |
else:
|
| 54 |
LogP_origin, rho_origin, mp_origin = '','',''
|
| 55 |
iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = ResolveChemical(chemName, IDtype, get_properties=get_properties)
|
|
@@ -81,7 +81,7 @@ def exp_post():
|
|
| 81 |
else:
|
| 82 |
is_metal, is_ceramic = CeramicOrMetal(smiles,100)
|
| 83 |
if is_metal:
|
| 84 |
-
return render_template('quantity_metalError.html', show_properties=show_properties, chemName=chemName, MW=MW,
|
| 85 |
LogP=LogP, rho=rho, mp=mp, iupac=iupac,
|
| 86 |
cas=cas, smiles=smiles, molImage=molImage,
|
| 87 |
LogP_origin=LogP_origin, rho_origin=rho_origin, mp_origin=mp_origin)
|
|
@@ -89,24 +89,29 @@ def exp_post():
|
|
| 89 |
MW = 1100.
|
| 90 |
|
| 91 |
M_expt = float(request.form['amount']) # amount
|
| 92 |
-
units = request.form['units']
|
| 93 |
mass = float(request.form['mass'])
|
| 94 |
Polymer_Density = float(request.form['density'])
|
| 95 |
Polymer_Volume = mass / Polymer_Density # vol
|
| 96 |
Surface_Area = float(request.form['area']) # area
|
| 97 |
-
Solvent_Volume = float(request.form['solventvol'])
|
| 98 |
-
Solvent_Name = request.form['solventname']
|
| 99 |
-
Swelling_percent = float(request.form['swelling'])
|
| 100 |
Swelling_wtfrac = Swelling_percent/100
|
| 101 |
-
Extraction_Time = float(request.form['time'])
|
| 102 |
-
K_expt = float(request.form['K'])
|
| 103 |
Solvent_MW = Solvent_MWs[Solvent_Name]
|
| 104 |
Solvent_Density = Solvent_Densities[Solvent_Name]
|
| 105 |
Solute_MW = MW
|
|
|
|
| 106 |
|
| 107 |
## extent of swelling, V_swelled/V_unswelled
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
# check that swelling is physically possible (swollen polymer volume is less than polymer+solvent volume)
|
| 111 |
if Solvent_Volume < Polymer_Volume*(Qv-1):
|
| 112 |
return render_template('quantity_error.html', message=f'Based on the information provided, the amount of swelling appears physically impossible. Please check the values you entered.')
|
|
@@ -118,6 +123,7 @@ def exp_post():
|
|
| 118 |
|
| 119 |
polymer = request.form['polymer']
|
| 120 |
|
|
|
|
| 121 |
# QRF is implemented for 25-75 C
|
| 122 |
if polymer == 'Other polymer':
|
| 123 |
use_qrf = True
|
|
@@ -128,28 +134,30 @@ def exp_post():
|
|
| 128 |
quantiles = list(np.linspace(0.0,1.0,201))
|
| 129 |
#quantiles = list(np.linspace(0.05,0.95,181))
|
| 130 |
if is_ceramic:
|
| 131 |
-
diff,domain_extrap = QRF_Ceramic(Polymer_Density, Polymer_Tg, quantiles=quantiles, T=T-273.15, worstcase='lo')
|
| 132 |
else:
|
| 133 |
-
diff,domain_extrap = QRF_Apply(Polymer_Density, Polymer_Tg, smiles, quantiles=quantiles, T=T-273.15)
|
| 134 |
if domain_extrap:
|
| 135 |
# outside training domain, default to Wilke-Chang
|
| 136 |
method = 'qrf/wc'
|
| 137 |
-
D_dist_noswell, D_dist_swell =
|
|
|
|
| 138 |
M0_pred = get_M_dist(D_dist_swell, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 139 |
else:
|
| 140 |
method = 'qrf'
|
| 141 |
-
D_dist_noswell, D_dist_swell =
|
|
|
|
| 142 |
M0_pred = get_M_dist(D_dist_swell, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 143 |
else:
|
| 144 |
## use categories
|
| 145 |
-
pIndex = np.argmax(polymers == polymer)
|
| 146 |
CHRIS_category = categories[pIndex]
|
| 147 |
CHRIS_flag = None
|
| 148 |
if CHRIS_category is None:
|
| 149 |
## worst-case for a generic polymer --> G2
|
| 150 |
CHRIS_flag = 'wc'
|
| 151 |
CHRIS_category = 'G2'
|
| 152 |
-
D_dist_noswell, D_dist_swell =
|
|
|
|
| 153 |
M0_pred = get_M_dist(D_dist_swell, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 154 |
if CHRIS_flag is None:
|
| 155 |
method = 'category'
|
|
@@ -164,10 +172,10 @@ def exp_post():
|
|
| 164 |
print('M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt, method, Qv, Swelling_volfrac')
|
| 165 |
print(M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt, method, Qv, Swelling_volfrac)
|
| 166 |
print(np.nanquantile(M0_pred, [0.05,0.5,0.95]))
|
| 167 |
-
V1,V2 = get_D_dists(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, 'G2', rng, return_DCs=False, N=N_sample)
|
| 168 |
-
V3 = get_M_dist(V2, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 169 |
-
print(np.nanquantile(V2, [0.05,0.5,0.95]))
|
| 170 |
-
print(np.nanquantile(V3, [0.05,0.5,0.95]))
|
| 171 |
|
| 172 |
# Generate the rate plot using matplotlib
|
| 173 |
#pngImageB64String = CdfPlot(M0_pred[~np.isnan(M0_pred)], units=units)
|
|
@@ -192,10 +200,9 @@ def exp_post():
|
|
| 192 |
tau_out = SigFigs(tau,6)
|
| 193 |
mass_units = SigFigs(mass_units,6)
|
| 194 |
|
| 195 |
-
return render_template('quantity_report.html', show_properties=show_properties, polymers=polymers, pIndex=pIndex,
|
| 196 |
-
area=Surface_Area, vol=Polymer_Volume, units=units, M=M_expt, M0=M0_out, time=Extraction_Time,
|
| 197 |
solventvol=Solvent_Volume, solventname=Solvent_Name, swelling=Swelling_percent, K=K_expt, T=T, tau=tau_out,
|
| 198 |
chemName=chemName, MW=MW, LogP=LogP, rho=rho, mp=mp, iupac=iupac, cas=cas, smiles=smiles, molImage=molImage, table=table,
|
| 199 |
LogP_origin=LogP_origin, rho_origin=rho_origin, mp_origin=mp_origin, ceramic=is_ceramic, methods=[method,round(Polymer_Tg-273.15),Polymer_Density],
|
| 200 |
mass=mass, mass_units=mass_units, density=Polymer_Density)
|
| 201 |
-
|
|
|
|
| 35 |
def exp_post():
|
| 36 |
|
| 37 |
Polymer_Tg = float(request.form['Polymer_Tg']) ## NOTE Tg is provided in C
|
| 38 |
+
T = float(request.form['T'])
|
| 39 |
Polymer_Tg += 273.15
|
| 40 |
T += 273.15
|
| 41 |
rng = np.random.Generator(np.random.PCG64(seed=12345))
|
|
|
|
| 49 |
|
| 50 |
if debug:
|
| 51 |
iupac, cas, smiles, MW, LogP, LogP_origin, rho, rho_origin, mp, mp_origin, molImage, error = ResolveChemical(chemName, IDtype, debug=debug, get_properties=['logp','rho','mp'])
|
| 52 |
+
LogP_origin, rho_origin, mp_origin = f' ({LogP_origin})', f' ({rho_origin})', f' ({mp_origin})',
|
| 53 |
else:
|
| 54 |
LogP_origin, rho_origin, mp_origin = '','',''
|
| 55 |
iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = ResolveChemical(chemName, IDtype, get_properties=get_properties)
|
|
|
|
| 81 |
else:
|
| 82 |
is_metal, is_ceramic = CeramicOrMetal(smiles,100)
|
| 83 |
if is_metal:
|
| 84 |
+
return render_template('quantity_metalError.html', show_properties=show_properties, chemName=chemName, MW=MW,
|
| 85 |
LogP=LogP, rho=rho, mp=mp, iupac=iupac,
|
| 86 |
cas=cas, smiles=smiles, molImage=molImage,
|
| 87 |
LogP_origin=LogP_origin, rho_origin=rho_origin, mp_origin=mp_origin)
|
|
|
|
| 89 |
MW = 1100.
|
| 90 |
|
| 91 |
M_expt = float(request.form['amount']) # amount
|
| 92 |
+
units = request.form['units']
|
| 93 |
mass = float(request.form['mass'])
|
| 94 |
Polymer_Density = float(request.form['density'])
|
| 95 |
Polymer_Volume = mass / Polymer_Density # vol
|
| 96 |
Surface_Area = float(request.form['area']) # area
|
| 97 |
+
Solvent_Volume = float(request.form['solventvol'])
|
| 98 |
+
Solvent_Name = request.form['solventname']
|
| 99 |
+
Swelling_percent = float(request.form['swelling'])
|
| 100 |
Swelling_wtfrac = Swelling_percent/100
|
| 101 |
+
Extraction_Time = float(request.form['time'])
|
| 102 |
+
K_expt = float(request.form['K'])
|
| 103 |
Solvent_MW = Solvent_MWs[Solvent_Name]
|
| 104 |
Solvent_Density = Solvent_Densities[Solvent_Name]
|
| 105 |
Solute_MW = MW
|
| 106 |
+
Solute_Vabc = get_V(smiles)
|
| 107 |
|
| 108 |
## extent of swelling, V_swelled/V_unswelled
|
| 109 |
+
if Swelling_wtfrac > 0:
|
| 110 |
+
Swelling_volfrac = Polymer_Density / (Solvent_Density * (1/Swelling_wtfrac-1) + Polymer_Density)
|
| 111 |
+
Qv = 1+Swelling_volfrac/(1-Swelling_volfrac)
|
| 112 |
+
else:
|
| 113 |
+
Swelling_volfrac = 0
|
| 114 |
+
Qv = 1
|
| 115 |
# check that swelling is physically possible (swollen polymer volume is less than polymer+solvent volume)
|
| 116 |
if Solvent_Volume < Polymer_Volume*(Qv-1):
|
| 117 |
return render_template('quantity_error.html', message=f'Based on the information provided, the amount of swelling appears physically impossible. Please check the values you entered.')
|
|
|
|
| 123 |
|
| 124 |
polymer = request.form['polymer']
|
| 125 |
|
| 126 |
+
pIndex = np.argmax(polymers == polymer)
|
| 127 |
# QRF is implemented for 25-75 C
|
| 128 |
if polymer == 'Other polymer':
|
| 129 |
use_qrf = True
|
|
|
|
| 134 |
quantiles = list(np.linspace(0.0,1.0,201))
|
| 135 |
#quantiles = list(np.linspace(0.05,0.95,181))
|
| 136 |
if is_ceramic:
|
| 137 |
+
diff,domain_extrap = QRF_Ceramic(Polymer_Density, Polymer_Tg-273.15, quantiles=quantiles, T=T-273.15, worstcase='lo')
|
| 138 |
else:
|
| 139 |
+
diff,domain_extrap = QRF_Apply(Polymer_Density, Polymer_Tg-273.15, smiles, quantiles=quantiles, T=T-273.15)
|
| 140 |
if domain_extrap:
|
| 141 |
# outside training domain, default to Wilke-Chang
|
| 142 |
method = 'qrf/wc'
|
| 143 |
+
D_dist_noswell, D_dist_swell = get_D_dists_new(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, Solute_Vabc, 'G2', rng, return_DCs=False, N=N_sample)
|
| 144 |
+
# D_dist_noswell, D_dist_swell = get_D_dists(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, 'G2', rng, return_DCs=False, N=N_sample)
|
| 145 |
M0_pred = get_M_dist(D_dist_swell, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 146 |
else:
|
| 147 |
method = 'qrf'
|
| 148 |
+
D_dist_noswell, D_dist_swell = get_D_dists_new(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, Solute_Vabc, CHRIS_category, rng, return_DCs=False, N=N_sample, input_Ds=diff)
|
| 149 |
+
#D_dist_noswell, D_dist_swell = get_D_dists(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, None, rng, return_DCs=False, N=N_sample, input_Ds=diff)
|
| 150 |
M0_pred = get_M_dist(D_dist_swell, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 151 |
else:
|
| 152 |
## use categories
|
|
|
|
| 153 |
CHRIS_category = categories[pIndex]
|
| 154 |
CHRIS_flag = None
|
| 155 |
if CHRIS_category is None:
|
| 156 |
## worst-case for a generic polymer --> G2
|
| 157 |
CHRIS_flag = 'wc'
|
| 158 |
CHRIS_category = 'G2'
|
| 159 |
+
D_dist_noswell, D_dist_swell = get_D_dists_new(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, Solute_Vabc, CHRIS_category, rng, return_DCs=False, N=N_sample, input_Ds=None)
|
| 160 |
+
#D_dist_noswell, D_dist_swell = get_D_dists(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, CHRIS_category, rng, return_DCs=False, N=N_sample)
|
| 161 |
M0_pred = get_M_dist(D_dist_swell, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 162 |
if CHRIS_flag is None:
|
| 163 |
method = 'category'
|
|
|
|
| 172 |
print('M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt, method, Qv, Swelling_volfrac')
|
| 173 |
print(M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt, method, Qv, Swelling_volfrac)
|
| 174 |
print(np.nanquantile(M0_pred, [0.05,0.5,0.95]))
|
| 175 |
+
#V1,V2 = get_D_dists(Swelling_wtfrac, T, Polymer_Tg, Solvent_Name, Solvent_MW, Solute_MW, 'G2', rng, return_DCs=False, N=N_sample)
|
| 176 |
+
#V3 = get_M_dist(V2, M_expt, Polymer_Volume, Surface_Area, Solvent_Volume, Extraction_Time*3600, K_expt=K_expt, Qv=Qv)
|
| 177 |
+
#print(np.nanquantile(V2, [0.05,0.5,0.95]))
|
| 178 |
+
#print(np.nanquantile(V3, [0.05,0.5,0.95]))
|
| 179 |
|
| 180 |
# Generate the rate plot using matplotlib
|
| 181 |
#pngImageB64String = CdfPlot(M0_pred[~np.isnan(M0_pred)], units=units)
|
|
|
|
| 200 |
tau_out = SigFigs(tau,6)
|
| 201 |
mass_units = SigFigs(mass_units,6)
|
| 202 |
|
| 203 |
+
return render_template('quantity_report.html', show_properties=show_properties, polymers=polymers, pIndex=pIndex,
|
| 204 |
+
area=Surface_Area, vol=Polymer_Volume, units=units, M=M_expt, M0=M0_out, time=Extraction_Time,
|
| 205 |
solventvol=Solvent_Volume, solventname=Solvent_Name, swelling=Swelling_percent, K=K_expt, T=T, tau=tau_out,
|
| 206 |
chemName=chemName, MW=MW, LogP=LogP, rho=rho, mp=mp, iupac=iupac, cas=cas, smiles=smiles, molImage=molImage, table=table,
|
| 207 |
LogP_origin=LogP_origin, rho_origin=rho_origin, mp_origin=mp_origin, ceramic=is_ceramic, methods=[method,round(Polymer_Tg-273.15),Polymer_Density],
|
| 208 |
mass=mass, mass_units=mass_units, density=Polymer_Density)
|
|
|