File size: 7,174 Bytes
a3c0189
d21d254
79f5ac2
d21d254
 
 
d33329a
d21d254
 
a26b7e6
d21d254
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8ba861b
 
d21d254
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3c0189
 
 
 
347cff1
 
 
 
d21d254
 
597c570
 
d21d254
 
347cff1
 
 
d21d254
347cff1
 
597c570
347cff1
 
d21d254
8ba861b
 
 
d21d254
8ba861b
 
d21d254
8ba861b
d21d254
 
8ba861b
d21d254
 
8ba861b
d21d254
8ba861b
d21d254
 
 
 
9b40e15
 
 
 
8ba861b
d21d254
8ba861b
 
d21d254
 
 
 
 
 
 
 
 
 
8ba861b
347cff1
a1eff75
 
 
d21d254
8ba861b
 
 
 
d21d254
 
 
 
 
8ba861b
 
 
 
d21d254
 
 
 
 
79f5ac2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1ed8291
 
 
79f5ac2
d21d254
 
 
 
79f5ac2
9b40e15
79f5ac2
347cff1
d21d254
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
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])