CHRIS / exposure3_module /exposure.py
Robert Elder
quantity module + qrf updates
d33329a
import sys,numbers
import numpy as np
import pandas as pd
from flask import render_template, request
from functions import SigFigs, Piringer, WilkeChang, SheetRelease, SheetRates, RatePlot
from functions import Piecewise, PowerLaw
from qrf.functions import QRF_Apply, QRF_Ceramic
from . import blueprint
from polymers import Polymers, Polymers3
from ChemID import *
import rdkit
from rdkit.Chem import AllChem as Chem
# get additional physical properties, options are: logp, rho, mp
#get_properties = [] # don't get any; this breaks ceramics logic
#get_properties = ['logp','rho','mp'] # get all three
get_properties = ['mp'] # only get mp
# show additional physical properties
show_properties = False
# output additional info for physical properties
debug = False
# flag for testing new polymer categories
#use_new = True
# load polymer data including Ap values
polymers, categories, params = Polymers3()
# load the index page for the exposure module
@blueprint.route('/exposure3', methods=['GET'])
def exposure():
return render_template('exposure3_index.html', polymers=polymers)
# build the report page for the exposure module
@blueprint.route('/exposure3', methods=['POST'])
def exp_post():
chemName = request.form['chemName']
IDtype = request.form['IDtype']
if debug:
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'])
LogP_origin, rho_origin, mp_origin = f' ({LogP_origin})', f' ({rho_origin})', f' ({mp_origin})',
else:
LogP_origin, rho_origin, mp_origin = '','',''
iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = ResolveChemical(chemName, IDtype, get_properties=get_properties)
if error > 0:
# TODO output more useful info
return render_template('exposure3_chemError.html')
#MW = SigFigs(MW, 6)
if 'logp' not in get_properties:
LogP = 'Not searched'
elif LogP is np.nan or LogP is None:
LogP = 'Not found'
else:
LogP = SigFigs(LogP, 4)
if 'rho' not in get_properties:
rho = 'Not searched'
elif rho is np.nan or rho is None:
rho = 'Not found'
else:
rho = SigFigs(rho, 4)
if 'mp' not in get_properties:
mp = 'Not searched'
elif mp is np.nan or mp is None:
mp = 'Not found'
# metals/ceramics logic
if isinstance(mp, numbers.Number):
is_metal, is_ceramic = CeramicOrMetal(smiles,mp)
else:
is_metal, is_ceramic = CeramicOrMetal(smiles,100)
#ceramic = False
#mol = Chem.MolFromSmiles(smiles)
#atom_num_list = [a.GetAtomicNum() for a in mol.GetAtoms()]
#is_metal = set(atom_num_list) <= METAL_ATOM_SET
if is_metal:
# if all atoms are metals -> this is a metal
return render_template('exposure3_metalError.html', show_properties=show_properties, chemName=chemName, MW=MW,
LogP=LogP, rho=rho, mp=mp, iupac=iupac,
cas=cas, smiles=smiles, molImage=molImage,
LogP_origin=LogP_origin, rho_origin=rho_origin, mp_origin=mp_origin)
#else:
if is_ceramic:
MW = 1100.
# get number of carbon-carbon bonds
#num_CC_bonds = sum([1 if b.GetBeginAtom().GetAtomicNum() == 6 and b.GetEndAtom().GetAtomicNum() == 6 else 0 for b in mol.GetBonds()])
#if not num_CC_bonds and (mp is not None) and mp > 700.:
# if not a metal, no C-C bonds, and mp > 700 (sodium chloride has mp ~ 800), assume ceramic...
#MW = 1100.
#ceramic = True
amount = float(request.form['amount'])
mass = float(request.form['mass'])
density = float(request.form['density'])
vol = mass / density
area = float(request.form['area'])
exposure = request.form['exposure']
polymer = request.form['polymer']
pIndex = np.argmax(polymers == polymer)
if exposure != 'limited':
time = 24.
else:
time = float(request.form['exptime'])
if exposure != 'long-term':
TTC = 0.12
else:
TTC = 0.0015
units = request.form['units']
if units == 'µg':
TTC *= 1000
polytg = ''
use_qrf = False
if polymer == 'Other polymer':
polytg = request.form['polytg']
if polytg == '':
# left blank, use old default (Wilke Chang), which is taken care of by pIndex
pass
else:
polytg = float(polytg)
use_qrf = True
#print('b', polytg, type(polytg), file=sys.stderr)
if use_qrf:
#print('using qrf', file=sys.stderr)
method = 'qrf'
if is_ceramic:
diff,domain_extrap = QRF_Ceramic(density, polytg, quantiles=[0.03,0.5,0.97])
else:
diff,domain_extrap = QRF_Apply(density, polytg, smiles, quantiles=[0.03,0.5,0.97])
diff = diff[2] # upper bound
if domain_extrap:
# outside training domain, default to Wilke-Chang
diff = Piecewise(MW, params[None])
method = 'qrf/wc'
else:
## use categories
category = categories[pIndex]
diff = Piecewise(MW, params[category])
domain_extrap = False
if category:
method = 'category'
else:
method = 'wc'
release = SheetRelease(amount, vol, area, time, diff)
MOS = TTC / release
# Generate the rate plot using matplotlib
#tarray = np.arange(1., 31., 1.)
#rates = SheetRates(amount, vol, area, tarray, diff)
#pngImageB64String = RatePlot(tarray, rates)
# Generate cumulative release at given times
tlist = [1.]
if len(request.form.getlist('exposure30d')):
tlist.append(30.)
if len(request.form.getlist('exposureuser')):
tlist.append(float(request.form['exposureuserbox']))
release_list = [SheetRelease(amount, vol, area, t*24, diff) for t in tlist]
#print(release_list, file=sys.stderr)
frac_list = [str(SigFigs(r/amount*100,2))+'%' for r in release_list]
release_list = [SigFigs(r,2) for r in release_list]
df_rel = pd.DataFrame(np.transpose([tlist,release_list,frac_list]),columns=['Exposure duration (days)',f'Cumulative exposure ({units})','Cumulative exposure (%)'])
df_rel['Exposure duration (days)'] = df_rel['Exposure duration (days)'].astype(float)
release_table = df_rel.sort_values(by='Exposure duration (days)').to_html(index=False)
release = SigFigs(release, 2)
MOS = SigFigs(MOS, 2)
diff = SigFigs(diff, 2)
return render_template('exposure3_report.html', show_properties=show_properties, polymers=polymers, pIndex=pIndex, release=release, release_table=release_table,
area=area, vol=vol, amount=amount, diff=diff, time=time, exposure=exposure, TTC=TTC, units=units,
MOS=MOS, chemName=chemName, MW=MW, LogP=LogP, rho=rho, mp=mp, iupac=iupac, cas=cas, smiles=smiles, molImage=molImage,
LogP_origin=LogP_origin, rho_origin=rho_origin, mp_origin=mp_origin, ceramic=is_ceramic, methods=[method,polytg,density])