dmsaylor commited on
Commit
1df71fb
·
2 Parent(s): aabb1599495b18

Merge branch 'CAselect'

Browse files
CHRIS.py CHANGED
@@ -1,7 +1,7 @@
1
  from flask import Flask, render_template
2
 
3
  app = Flask(__name__)
4
- app.debug = False
5
 
6
  from color_module import blueprint
7
  app.register_blueprint(blueprint)
 
1
  from flask import Flask, render_template
2
 
3
  app = Flask(__name__)
4
+ app.debug = True
5
 
6
  from color_module import blueprint
7
  app.register_blueprint(blueprint)
ChemID.py CHANGED
@@ -1,4 +1,6 @@
1
  import sys,os,glob,re,string
 
 
2
  import nltk
3
  import pandas as pd
4
  import numpy as np
 
1
  import sys,os,glob,re,string
2
+ from collections import Counter
3
+ from operator import itemgetter
4
  import nltk
5
  import pandas as pd
6
  import numpy as np
color2_module/colors.py CHANGED
@@ -1,13 +1,28 @@
1
  from flask import Flask, render_template, request
2
  import numpy as np
3
- from functions import SigFigs, Piringer, WilkeChang, SheetRelease
4
  from functions import Piecewise, PowerLaw
5
  from . import blueprint
6
  from polymers import Polymers, Polymers2
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  # flag for testing new polymer categories
9
  use_new = True
10
 
 
 
 
11
  # load polymer data including Ap values
12
  if not use_new:
13
  polymers, Ap = Polymers()
@@ -15,22 +30,21 @@ else:
15
  polymers, categories, params = Polymers2()
16
 
17
  # Named color additives, TI values, and Mw
18
- nCA = 14
19
- caData = np.zeros((nCA,), dtype=[('name', 'a75'), ('TI', 'd'), ('MW', 'd')])
20
- caData[0] = ('Titanium dioxide (CAS#:13463-67-7)', 1.0, 1100.)
21
- caData[1] = ('Carbon black (CAS#:1333-86-4)', 2.0, 1100.)
22
- caData[2] = ('Pigment brown 24 (CAS#:68186-90-3)', 0.5, 1100.)
23
- caData[3] = ('Zinc Oxide (CAS#:1314-13-2)', 0.05, 1100.)
24
- caData[4] = ('Pigment Red 101 (CAS#: 1309-37-1)', 1.0, 1100.)
25
- caData[5] = ('Solvent violet 13 (CAS#:81-48-1)', 0.0013, 319.4)
26
- caData[6] = ('Manganese phthalocyanine (CAS#:14325-24-7)', 0.15, 567.5)
27
- caData[7] = ('Pigment blue 15 (CAS#:147-14-8)', 0.15, 576.1)
28
- caData[8] = ('Phthalocyanine green (CAS#:1326-53-6)', 0.15, 1092.8)
29
- caData[9] = ('Ultramarine blue (CAS#:57445-37-5)', 3.3, 1100.)
30
- caData[10] = ('Pigment Yellow 138 (CAS#:30125-47-4)', 1.0, 693.96)
31
- caData[11] = ('Other metal oxide color additive', 1.0, 1100.0)
32
- caData[12] = ('Other non-metal oxide color additive', 1.0, 1100.0)
33
- caData[13] = ('Other color additive associated compound', 1.0, 1100.0)
34
 
35
  CAs = np.zeros(nCA, dtype='object')
36
  caMW = np.zeros(nCA, dtype='object')
@@ -50,6 +64,7 @@ def colors():
50
 
51
  @blueprint.route('/color2', methods=['POST'])
52
  def app_post():
 
53
  amount = float(request.form["amount"])
54
  mass = float(request.form["mass"])
55
  density = float(request.form["density"])
@@ -63,31 +78,73 @@ def app_post():
63
 
64
  TI = caData[caIndex][1]
65
  impurity = 1.
66
- MW = 1100.
67
  isCA = True
68
  chemName = ''
69
 
70
- if caIndex < 11:
71
- MW = caData[caIndex][2]
72
- chemName = '*' + caData[caIndex][0].decode('UTF-8') + '*'
73
  impurity = float(request.form["impurity"]) * amount * 1e-2
74
- if caIndex == 11:
75
- MW = caData[caIndex][2]
76
- chemName = request.form["chemName"] if "chemName" in request.form else "CHEMICAL NAME NOT PROVIDED"
77
- chemName = '*' + chemName + '*'
 
 
 
 
78
  impurity = float(request.form["impurity"]) * amount * 1e-2
79
  if caIndex == 12:
80
- MW = float(request.form["MW"])
81
- chemName = request.form["chemName"] if "chemName" in request.form else "CHEMICAL NAME NOT PROVIDED"
82
- chemName = '*' + chemName + '*'
83
- impurity = float(request.form["impurity"]) * amount * 1e-2
84
- if caIndex == 13:
85
  isCA = False
86
- MW = float(request.form["MW"])
87
- chemName = request.form["chemName"] if "chemName" in request.form else "CHEMICAL NAME NOT PROVIDED"
88
- chemName = '*' + chemName + '*'
89
- impurity = float(request.form["impurity"]) * amount * 1e-2
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  if exposure != "limited":
92
  time = 24.
93
  else:
@@ -125,9 +182,13 @@ def app_post():
125
  iMOS = SigFigs(iMOS, 2)
126
  impurity = SigFigs(impurity, 2)
127
 
128
- return render_template('color2_report.html', polymers=polymers, pIndex=pIndex, caIndex=caIndex, release=release,
129
- assume=assume,
130
- area=area, vol=vol, amount=amount, diff=diff, time=time, exposure=exposure, TTC=TTC,
131
- isCA=isCA, TI=TI, MOS=MOS,
132
- chemName=chemName, impurity=impurity, iMOS=iMOS)
 
 
 
 
133
 
 
1
  from flask import Flask, render_template, request
2
  import numpy as np
3
+ from functions import SigFigs, Piringer, WilkeChang, SheetRelease, SheetRates, RatePlot
4
  from functions import Piecewise, PowerLaw
5
  from . import blueprint
6
  from polymers import Polymers, Polymers2
7
+ from ChemID import ResolveChemical, ImageFromSmiles, Imageto64
8
+ import rdkit
9
+ from rdkit.Chem import AllChem as Chem
10
+
11
+ # get additional physical properties, options are: logp, rho, mp
12
+ #get_properties = [] # don't get any; this breaks ceramics logic
13
+ #get_properties = ['logp','rho','mp'] # get all three
14
+ get_properties = ['mp'] # only get mp
15
+ # show additional physical properties
16
+ show_properties = False
17
+ # output additional info for physical properties
18
+ debug = False
19
 
20
  # flag for testing new polymer categories
21
  use_new = True
22
 
23
+ ORGANIC_ATOM_SET = {5, 6, 7, 8, 9, 15, 16, 17, 35, 53}
24
+ METAL_ATOM_SET = set([3,4,11,12,13] + list(range(19,31+1)) + list(range(37,50+1)) + list(range(55,84+1)) + list(range(87,114+1)) + [116])
25
+
26
  # load polymer data including Ap values
27
  if not use_new:
28
  polymers, Ap = Polymers()
 
30
  polymers, categories, params = Polymers2()
31
 
32
  # Named color additives, TI values, and Mw
33
+ nCA = 13
34
+ caData = np.zeros((nCA,), dtype=[('name', 'a75'), ('TI', 'd'), ('MW', 'd'),('CAS', 'a75')])
35
+ caData[0] = ('Titanium dioxide (CAS#:13463-67-7)', 1.0, 1100., '13463-67-7')
36
+ caData[1] = ('Carbon black (CAS#:1333-86-4)', 2.0, 1100., '1333-86-4')
37
+ caData[2] = ('Pigment brown 24 (CAS#:68186-90-3)', 0.5, 1100., '68186-90-3')
38
+ caData[3] = ('Zinc Oxide (CAS#:1314-13-2)', 0.05, 1100., '1314-13-2')
39
+ caData[4] = ('Pigment Red 101 (CAS#: 1309-37-1)', 1.0, 1100., '1309-37-1')
40
+ caData[5] = ('Solvent violet 13 (CAS#:81-48-1)', 0.0013, 319.4, '81-48-1')
41
+ caData[6] = ('Manganese phthalocyanine (CAS#:14325-24-7)', 0.15, 567.5, '14325-24-7')
42
+ caData[7] = ('Pigment blue 15 (CAS#:147-14-8)', 0.15, 576.1, '147-14-8')
43
+ caData[8] = ('Phthalocyanine green (CAS#:1328-53-6)', 0.15, 1092.8, '1328-53-6')
44
+ caData[9] = ('Ultramarine blue (CAS#:57455-37-5)', 3.3, 1100., '57455-37-5')
45
+ caData[10] = ('Pigment Yellow 138 (CAS#:30125-47-4)', 1.0, 693.96, '30125-47-4')
46
+ caData[11] = ('Other color additive', 1.0, 1100.0, ' ')
47
+ caData[12] = ('Other color additive associated compound', 1.0, 1100.0, ' ')
 
48
 
49
  CAs = np.zeros(nCA, dtype='object')
50
  caMW = np.zeros(nCA, dtype='object')
 
64
 
65
  @blueprint.route('/color2', methods=['POST'])
66
  def app_post():
67
+
68
  amount = float(request.form["amount"])
69
  mass = float(request.form["mass"])
70
  density = float(request.form["density"])
 
78
 
79
  TI = caData[caIndex][1]
80
  impurity = 1.
 
81
  isCA = True
82
  chemName = ''
83
 
84
+ if caIndex <= 10:
85
+ IDtype = 'CAS'
86
+ chemName = caData[caIndex][3].decode('UTF-8')
87
  impurity = float(request.form["impurity"]) * amount * 1e-2
88
+ # problems:
89
+ # o C.I. Pigment Brown 24 = 68186-90-3, kludge "works"
90
+ # o Manganese(II) phthalocyanine = 14325-24-7, kludge "works"
91
+ # o Phthalocyanine green = 1326-53-6 -> 1328-53-6, corrected CAS works
92
+ # o Ultramarine blue = 57445-37-5 -> 57455-37-5, corrected CAS works
93
+ if caIndex > 10:
94
+ chemName = request.form["chemName"]
95
+ IDtype = request.form["IDtype"]
96
  impurity = float(request.form["impurity"]) * amount * 1e-2
97
  if caIndex == 12:
 
 
 
 
 
98
  isCA = False
 
 
 
 
99
 
100
+ print(chemName)
101
+ if chemName == '68186-90-3':
102
+ #IDtype = 'SMILES'
103
+ #chemName = 'O=[Ti]=O.O=[Sb]O[Sb](=O)=O.O=[Cr]O[Cr]=O'
104
+ #iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = ResolveChemical(chemName, IDtype, get_properties=get_properties)
105
+ iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = None, chemName, 'O=[Ti]=O.O=[Sb]O[Sb]=O.O=[Cr]O[Cr]=O', 1100, None, None, 1001, None, 0
106
+ im = ImageFromSmiles(smiles)
107
+ im64 = Imageto64(im)
108
+ molImage = im64
109
+ elif chemName == '14325-24-7':
110
+ IDtype = 'SMILES'
111
+ chemName = 'C1=CC=C2C(=C1)C3=NC4=NC(=NC5=C6C=CC=CC6=C([N-]5)N=C7C8=CC=CC=C8C(=N7)N=C2[N-]3)C9=CC=CC=C94.[Mn+2]'
112
+ iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = ResolveChemical(chemName, IDtype, get_properties=get_properties)
113
+ #iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = None, chemName, 'C1=CC=C2C(=C1)C3=NC4=NC(=NC5=C6C=CC=CC6=C([N-]5)N=C7C8=CC=CC=C8C(=N7)N=C2[N-]3)C9=CC=CC=C94.[Mn+2]', 567.5, None, None, 500, None, 0
114
+ #elif chemName == '1326-53-6':
115
+ # IDtype = 'SMILES'
116
+ # chemName = 'C1=C2C(=C(C(=C1Cl)Cl)Cl)C3=NC4=NC(=NC5=NC(=NC6=C7C(=C([N-]6)N=C2[N-]3)C(=C(C(=C7Cl)Cl)Cl)Cl)C8=C5C(=C(C(=C8Cl)Cl)Cl)Cl)C9=C4C(=C(C(=C9Cl)Cl)Cl)Cl.[Cu+2]'
117
+ # iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = ResolveChemical(chemName, IDtype, get_properties=get_properties)
118
+ else:
119
+ iupac, cas, smiles, MW, LogP, rho, mp, molImage, error = ResolveChemical(chemName, IDtype, get_properties=get_properties)
120
+
121
+ if error > 0:
122
+ # TODO output more useful info
123
+ return render_template('chemError.html')
124
+
125
+ # metals/ceramics logic
126
+ mol = Chem.MolFromSmiles(smiles)
127
+ #mol = Chem.AddHs(mol)
128
+ #natoms = mol.GetNumAtoms()
129
+ ceramic = False
130
+ atom_num_list = [a.GetAtomicNum() for a in mol.GetAtoms()]
131
+ is_metal = set(atom_num_list) <= METAL_ATOM_SET
132
+ #is_metal = all(a.GetAtomicNum() in metal_nums for a in mol.GetAtoms())
133
+ #is_organic = set(atom_num_list) <= ORGANIC_ATOM_SET
134
+ num_CC_bonds = sum([1 if b.GetBeginAtom().GetAtomicNum() == 6 and b.GetEndAtom().GetAtomicNum() == 6 else 0 for b in mol.GetBonds()])
135
+ if is_metal:
136
+ # if all atoms are metals -> this is a metal
137
+ return render_template('metalError.html', show_properties=show_properties, chemName=chemName, MW=MW,
138
+ LogP=LogP, rho=rho, mp=mp, iupac=iupac,
139
+ cas=cas, smiles=smiles, molImage=molImage)
140
+ #LogP_origin=LogP_origin, rho_origin=rho_origin, mp_origin=mp_origin)
141
+ else:
142
+ if not num_CC_bonds and (type(mp) is float or type(mp) is int) and mp > 1000.:
143
+ # if not a metal and no carbon-carbon bonds but melting point > 1000, assume ceramic
144
+ MW = 1100.
145
+ ceramic = True
146
+
147
+ # Exposure type
148
  if exposure != "limited":
149
  time = 24.
150
  else:
 
182
  iMOS = SigFigs(iMOS, 2)
183
  impurity = SigFigs(impurity, 2)
184
 
185
+ # Generate the rate plot using matplotlib
186
+ tarray = np.arange(1., 31., 1.)
187
+ rates = SheetRates(amount, vol, area, tarray, diff)
188
+ pngImageB64String = RatePlot(tarray, rates)
189
+
190
+ return render_template('color2_report.html', caIndex=caIndex, TI=TI, isCA=isCA, show_properties=show_properties, polymers=polymers, pIndex=pIndex, release=release,
191
+ assume=assume, area=area, vol=vol, amount=amount, diff=diff, time=time, exposure=exposure, TTC=TTC,
192
+ MOS=MOS, chemName=chemName, image=pngImageB64String, MW=MW, LogP=LogP, rho=rho, mp=mp, iupac=iupac, cas=cas, smiles=smiles, molImage=molImage,
193
+ ceramic=ceramic, impurity=impurity, iMOS=iMOS)
194
 
color2_module/templates/chemError.html ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>CHRIS-ChemError</title>
6
+ <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles.css') }}">
7
+
8
+ </head>
9
+
10
+ <img src="{{ url_for('static',filename='images/FDAlogo.png') }}" style="float: left;" height="100"/>
11
+ <img src="{{ url_for('static',filename='images/FDAgraphic.png') }}" style="float: right;" height="100"/>
12
+ <br clear="all" />
13
+
14
+ <body>
15
+
16
+ <div style="font-size:5rem;text-align:center"> &#129318; </div>
17
+
18
+ <p style="font-size:2rem;text-align:center">
19
+ Uh-oh! Something went wrong. We were unable to match your chemical. Please return to the previous page and try a
20
+ different identifier.
21
+ </p>
22
+
23
+
24
+ </body>
color2_module/templates/color2_index.html CHANGED
@@ -16,7 +16,7 @@
16
  </header>
17
 
18
  <p> For details on how to use the CHRIS color additive module, please read the <a href="{{url_for('.static', filename='README.html')}}"> instructions</a> and
19
- <a href="https://www.fda.gov/media/163472/download"> Summary of Evidence and Basis of Qualification (SEBQ)</a>, which includes limitations of use. Answers to frequently asked questions can be
20
  found <a href="{{url_for('.static', filename='FAQ.html')}}"> here</a>. For a history of updates, please see the <a href="{{url_for('.static', filename='Changelog.html')}}"> changelog</a>. </p>
21
 
22
  <body>
@@ -34,11 +34,14 @@ Identity: <select name="CA" id="CA" onchange="javascript:caCheck();">
34
  {% endfor %}
35
  </select>
36
  <span id="otherID" style="display:none">
37
- &nbsp; &rArr; Chemical name: <input name="chemName" id="chemName" type="text" value="ENTER CHEMICAL NAME" required>
 
 
 
 
 
38
  </span> <br>
39
 
40
- Molecular weight (g/mol): <input name="MW" id="MW" step="any" value="1100" min="0.0" max="1100.0" type="number" disabled required><br>
41
-
42
  Amount (mg): <input name="amount" id="amount" value="1.0" step="any" min="0.000001" type="number" required> <br>
43
 
44
  Total impurity concentration (%): <input name="impurity" id="impurity" value="0.1" step="any" min="0.000001" max='100.0' type="number" required> <br>
@@ -48,25 +51,17 @@ Total impurity concentration (%): <input name="impurity" id="impurity" value="0.
48
  <script type="text/javascript">
49
 
50
  function caCheck() {
51
- var caMW = ['{{caMW[0]}}','{{caMW[1]}}','{{caMW[2]}}','{{caMW[3]}}','{{caMW[4]}}','{{caMW[5]}}','{{caMW[6]}}','{{caMW[7]}}','{{caMW[8]}}','{{caMW[9]}}','{{caMW[10]}}','{{caMW[11]}}','{{caMW[12]}}','{{caMW[13]}}'];
52
  var iCA = parseInt(document.getElementById("CA").selectedIndex);
53
 
54
-
55
- document.getElementById('MW').disabled = true;
56
  document.getElementById('impurity').disabled = false;
57
 
58
- if (iCA >= 13) {
59
- // document.getElementById('impurity').disabled = true;
60
- }
61
- if (iCA >= 12) {
62
- document.getElementById('MW').disabled = false;
63
- }
64
  if (iCA >= 11) {
65
  document.getElementById('otherID').style.display = "inline";
66
- document.getElementById('chemName').value = "ENTER CHEMICAL NAME";
 
67
  } else {
68
- document.getElementById("MW").value = parseFloat(caMW[iCA]);
69
  document.getElementById('otherID').style.display = "none";
 
70
  }
71
  }
72
 
@@ -83,8 +78,10 @@ $(window).on('pageshow', function() { caCheck(); });
83
  <h4 class="modal-title">Color additive</h4>
84
  </div>
85
  <div class="modal-body">
86
- <p><em>Identity</em> - Select the color additive in the component being evaluated via the pull down list. If the color additive is not explicitly listed, please choose either "Other metal oxide color additive" or "Other non-metal oxide color additive" and enter the chemical name, including CAS # if known. If "Other non-metal oxide color additive" is selected, please enter the molecular weight of the color additive in grams per mole. If you are evaluating an additive associated with a color additive please select "Other color additive associated compound" and enter the chemical name and molecular weight. Note that CHRIS is limited to color additive associated substances with molecular weight up to 1100 g/mol. For compounds with molecular weight > 1100 g/mol, this value can be used for a conservative exposure estimate.
87
- <p><em>Molecular weight</em> - Enter the molecular weight of the substance in grams per mole.</p>
 
 
88
  <p><em>Amount</em> - Enter the total mass of the substance in the component being evaluated expressed in milligrams.</p>
89
  <p><em>Total impurity concentration</em> - If you have selected a color additive, please enter the combined concentration of all impurities associated with the color additive as a percentage (% mass/mass).</p>
90
  </div>
 
16
  </header>
17
 
18
  <p> For details on how to use the CHRIS color additive module, please read the <a href="{{url_for('.static', filename='README.html')}}"> instructions</a> and
19
+ <a href="{{url_for('.static', filename='COU.html')}}"> Context of Use (CoU)</a>, which includes limitations of use. Answers to frequently asked questions can be
20
  found <a href="{{url_for('.static', filename='FAQ.html')}}"> here</a>. For a history of updates, please see the <a href="{{url_for('.static', filename='Changelog.html')}}"> changelog</a>. </p>
21
 
22
  <body>
 
34
  {% endfor %}
35
  </select>
36
  <span id="otherID" style="display:none">
37
+ &nbsp; &rArr; Identifier type: <select name="IDtype">
38
+ <option value="CAS" selected>CAS</option>
39
+ <option value="SMILES" >SMILES</option>
40
+ <option value="common" >Common name</option>
41
+ </select>
42
+ Identifier: <input name="chemName" id="chemName" type="text" value="">
43
  </span> <br>
44
 
 
 
45
  Amount (mg): <input name="amount" id="amount" value="1.0" step="any" min="0.000001" type="number" required> <br>
46
 
47
  Total impurity concentration (%): <input name="impurity" id="impurity" value="0.1" step="any" min="0.000001" max='100.0' type="number" required> <br>
 
51
  <script type="text/javascript">
52
 
53
  function caCheck() {
 
54
  var iCA = parseInt(document.getElementById("CA").selectedIndex);
55
 
 
 
56
  document.getElementById('impurity').disabled = false;
57
 
 
 
 
 
 
 
58
  if (iCA >= 11) {
59
  document.getElementById('otherID').style.display = "inline";
60
+ document.getElementById('chemName').value = "";
61
+ document.getElementById('chemName').required = true;
62
  } else {
 
63
  document.getElementById('otherID').style.display = "none";
64
+ document.getElementById('chemName').required = false;
65
  }
66
  }
67
 
 
78
  <h4 class="modal-title">Color additive</h4>
79
  </div>
80
  <div class="modal-body">
81
+ <p><em>Identity</em> - Select the color additive in the component being evaluated via the pull down list.
82
+ If the color additive is not explicitly listed, please choose "Other color additive" and ...
83
+ If you are evaluating an additive associated with a color additive please select "Other color additive associated compound" and
84
+ enter the chemical name and molecular weight ...
85
  <p><em>Amount</em> - Enter the total mass of the substance in the component being evaluated expressed in milligrams.</p>
86
  <p><em>Total impurity concentration</em> - If you have selected a color additive, please enter the combined concentration of all impurities associated with the color additive as a percentage (% mass/mass).</p>
87
  </div>
color2_module/templates/color2_report.html CHANGED
@@ -8,6 +8,28 @@
8
  <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
9
  <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles.css') }}">
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  </head>
12
 
13
  <header>
@@ -20,10 +42,34 @@
20
  <script> document.write(new Date().toLocaleDateString()); </script>.
21
  </p>
22
 
23
- <h3>Exposure </h3>
24
-
25
- <p>
26
- <u> Diffusion calculation for {{chemName}} leaching from {{polymers[pIndex]}} estimates a worst case single day
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  exposure = {{release}} mg. </u>
28
  <p>
29
 
@@ -52,7 +98,14 @@ where \( \tau= D t A^2 / V^2 \) and \( A \) and \( V \) are the surface area and
52
  \( t \) = {{time}} h <br>
53
  <p>
54
 
55
- <h3> Assumptions </h3>
 
 
 
 
 
 
 
56
 
57
  {% if assume[0] and assume[1] and assume[2] and assume[3] and assume[4] %}
58
 
@@ -93,7 +146,7 @@ where \( \tau= D t A^2 / V^2 \) and \( A \) and \( V \) are the surface area and
93
 
94
  {% endif %}
95
 
96
- <h3> Screening level toxicological risk assessment </h3>
97
 
98
  {% if caIndex > 10 %}
99
 
@@ -164,7 +217,7 @@ of {{MOS}}.
164
 
165
  {% endif %}
166
 
167
- <h3> Impurities </h3>
168
 
169
  {% if iMOS >= 1 %}
170
 
 
8
  <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
9
  <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles.css') }}">
10
 
11
+ <style>
12
+ * {
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ /* Create two equal columns that floats next to each other */
17
+ .column {
18
+ float: left;
19
+ width: 50%;
20
+ padding: 10px;
21
+ vertical-align: top;
22
+ align: center;
23
+ }
24
+
25
+ /* Clear floats after the columns */
26
+ .row:after {
27
+ content: "";
28
+ display: table;
29
+ clear: both;
30
+ }
31
+ </style>
32
+
33
  </head>
34
 
35
  <header>
 
42
  <script> document.write(new Date().toLocaleDateString()); </script>.
43
  </p>
44
 
45
+ <h2> Compound </h2>
46
+
47
+ <div class="container">
48
+ <div class="row">
49
+ <div class="column">
50
+ Input :: {{chemName}} <br> <br>
51
+ IUPAC Name :: {{iupac}} <br> <br>
52
+ CAS :: {{cas}} <br> <br>
53
+ Molecular weight (g/mol) :: {{'%0.4f'%MW|float}}
54
+ {% if ceramic %} :: ceramic detected, assume maximum Mw {% endif %}
55
+ <br> <br>
56
+ {% if show_properties %}
57
+ LogKow :: {{LogP}}{{LogP_origin}}<br> <br>
58
+ Density (g/cm<sup>3</sup>) :: {{rho}}{{rho_origin}}<br> <br>
59
+ Melting point (&deg;C) :: {{mp}}{{mp_origin}}<br> <br>
60
+ {% endif %}
61
+ SMILES :: {{smiles}}
62
+ </div>
63
+ <div class="column">
64
+ <img src="{{molImage}}"/>
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <h2>Exposure </h2>
70
+
71
+ <p>
72
+ <u> Diffusion calculation for leaching from {{polymers[pIndex]}} estimates a worst case single day
73
  exposure = {{release}} mg. </u>
74
  <p>
75
 
 
98
  \( t \) = {{time}} h <br>
99
  <p>
100
 
101
+ <p>
102
+ In addition to the maximum daily (day 1) release rate, it can be helpful to examine the decay in release rate over time predicted by the model,
103
+ which is illustrated for the first 30 days of exposure in the plot below:
104
+ </p>
105
+
106
+ <img src="{{ image }}"/>
107
+
108
+ <h2> Assumptions </h2>
109
 
110
  {% if assume[0] and assume[1] and assume[2] and assume[3] and assume[4] %}
111
 
 
146
 
147
  {% endif %}
148
 
149
+ <h2> Screening level toxicological risk assessment </h2>
150
 
151
  {% if caIndex > 10 %}
152
 
 
217
 
218
  {% endif %}
219
 
220
+ <h2> Impurities </h2>
221
 
222
  {% if iMOS >= 1 %}
223
 
color2_module/templates/metalError.html ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>CHRIS-ChemError</title>
6
+ <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles.css') }}">
7
+
8
+ <style>
9
+ * {
10
+ box-sizing: border-box;
11
+ }
12
+
13
+ /* Create two equal columns that floats next to each other */
14
+ .column {
15
+ float: left;
16
+ width: 50%;
17
+ padding: 10px;
18
+ vertical-align: top;
19
+ align: center;
20
+ }
21
+
22
+ /* Clear floats after the columns */
23
+ .row:after {
24
+ content: "";
25
+ display: table;
26
+ clear: both;
27
+ }
28
+ </style>
29
+
30
+ </head>
31
+
32
+ <img src="{{ url_for('static',filename='images/FDAlogo.png') }}" style="float: left;" height="100"/>
33
+ <img src="{{ url_for('static',filename='images/FDAgraphic.png') }}" style="float: right;" height="100"/>
34
+ <br clear="all" />
35
+
36
+ <body>
37
+
38
+ <div style="font-size:5rem;text-align:center"> &#129318; </div>
39
+
40
+ <h2> Compound </h2>
41
+
42
+ <div class="container">
43
+ <div class="row">
44
+ <div class="column">
45
+ Input :: {{chemName}} <br> <br>
46
+ IUPAC Name :: {{iupac}} <br> <br>
47
+ CAS :: {{cas}} <br> <br>
48
+ Molecular weight (g/mol) :: {{'%0.4f'%MW|float}} <br> <br>
49
+ {% if show_properties %}
50
+ LogKow :: {{LogP}}{{LogP_origin}} <br> <br>
51
+ Density (g/cm<sup>3</sup>) :: {{rho}}{{rho_origin}} <br> <br>
52
+ Melting point (&deg;C) :: {{mp}}{{mp_origin}} <br> <br>
53
+ {% endif %}
54
+ SMILES :: {{smiles}}
55
+ </div>
56
+ <div class="column">
57
+ <img src="{{molImage}}"/>
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ <p style="font-size:2rem;text-align:center">
63
+ Unfortunately, CHRIS cannot be used for metals. Please return to the previous page to evaluate
64
+ a different chemical.
65
+ </p>
66
+
67
+
68
+ </body>
efficiency_module/static/efficiency_COU.html CHANGED
@@ -42,20 +42,20 @@ The salient limitations are enumerated below:</p>
42
  Therefore, the output is only applicable to compounds that are
43
  introduced either intentionally or unintentionally during synthesis
44
  (e.g., residual monomers and oligomers, catalysts, initiators) or
45
- compounding (e.g., stabilizers, antioxidants, plasticizers) are within
46
- scope. The model is not appropriate for surface residuals from
47
- processing, cleaning, and sterilization.</li>
48
  <li>The solvent is “perfectly mixed”. This should be a reasonable
49
- assumption provided the samples are adequately agitated in a static bath
50
- over the timeframe of the testing. However, this assumption may not be
51
- appropriate if sufficient agitation is not applied and a boundary layer
52
- develops that slows the release rate or if the extraction is conducted
53
- under flow conditions.</li>
54
  <li>Possible chemical reactions are not considered. Therefore, if the
55
  polymer matrix undergoes substantive degradation during the extraction
56
  test, the predictions may not be relevant. Further, the model does not
57
- consider the potential for individual extractable compounds to
58
- degrade.</li>
59
  <li>The test article is comprised of a single polymer matrix. In
60
  practice, complex devices may be comprised of multiple components and/or
61
  polymer matrices. In these scenarios, careful consideration of the
 
42
  Therefore, the output is only applicable to compounds that are
43
  introduced either intentionally or unintentionally during synthesis
44
  (e.g., residual monomers and oligomers, catalysts, initiators) or
45
+ compounding (e.g., stabilizers, antioxidants, plasticizers). The model
46
+ is not appropriate for surface residuals from processing, cleaning, and
47
+ sterilization.</li>
48
  <li>The solvent is “perfectly mixed”. This should be a reasonable
49
+ assumption provided the samples are adequately agitated over the
50
+ timeframe of the testing. However, this assumption may not be
51
+ appropriate if sufficient agitation is not applied and a signficant
52
+ boundary layer develops that slows the release rate or if the extraction
53
+ is conducted under flow conditions.</li>
54
  <li>Possible chemical reactions are not considered. Therefore, if the
55
  polymer matrix undergoes substantive degradation during the extraction
56
  test, the predictions may not be relevant. Further, the model does not
57
+ consider the potential for individual extractable compounds to degrade
58
+ over the selected timeframe.</li>
59
  <li>The test article is comprised of a single polymer matrix. In
60
  practice, complex devices may be comprised of multiple components and/or
61
  polymer matrices. In these scenarios, careful consideration of the
exposure2_module/exposure.py CHANGED
@@ -71,7 +71,7 @@ def exp_post():
71
  # metals/ceramics logic
72
  mol = Chem.MolFromSmiles(smiles)
73
  mol = Chem.AddHs(mol)
74
- natoms = mol.GetNumAtoms()
75
  metal_nums = [3,4,11,12,13] + list(range(19,31+1)) + list(range(37,50+1)) + list(range(55,84+1)) + list(range(87,114+1)) + [116]
76
  ceramic = False
77
  if all(a.GetAtomicNum() in metal_nums for a in mol.GetAtoms()):
 
71
  # metals/ceramics logic
72
  mol = Chem.MolFromSmiles(smiles)
73
  mol = Chem.AddHs(mol)
74
+ #natoms = mol.GetNumAtoms()
75
  metal_nums = [3,4,11,12,13] + list(range(19,31+1)) + list(range(37,50+1)) + list(range(55,84+1)) + list(range(87,114+1)) + [116]
76
  ceramic = False
77
  if all(a.GetAtomicNum() in metal_nums for a in mol.GetAtoms()):