Robert Elder commited on
Commit
2e2d51b
·
1 Parent(s): fc39fc6

updating chemError pages to include links to websites to manually resolve SMILES

Browse files
CHRIS.py CHANGED
@@ -1,7 +1,35 @@
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
+ from werkzeug.middleware.profiler import ProfilerMiddleware
3
 
4
  app = Flask(__name__)
5
+ app.debug = True
6
+
7
+ # Profile every request (or limit with restrictions)
8
+ #app.wsgi_app = ProfilerMiddleware(
9
+ # app.wsgi_app,
10
+ # restrictions=[30], # show top 30 lines
11
+ # sort_by=("tottime",) # total time spent in function body
12
+ #)
13
+
14
+ ## DEBUGGING
15
+ if 0:
16
+ from pprint import pformat
17
+ from flask import g, request
18
+
19
+ @app.after_request
20
+ def dump_chem_trace(response):
21
+ trace = getattr(g, "chem_trace", None)
22
+ if trace:
23
+ bases = sorted(set(getattr(g, "chem_bases", [])))
24
+ payload = {
25
+ "path": request.path,
26
+ "query": request.values.to_dict(flat=False),
27
+ "base_urls": bases,
28
+ "remote_trace": [x for x in trace if x.get("kind") == "remote"],
29
+ "app_trace": [x for x in trace if x.get("kind") == "app"],
30
+ }
31
+ app.logger.warning("CHEMTRACE\n%s", pformat(payload, sort_dicts=False, width=120))
32
+ return response
33
 
34
  #from color_module import blueprint
35
  #app.register_blueprint(blueprint)
ChemID.py CHANGED
@@ -13,6 +13,178 @@ import urllib
13
  import requests
14
  import json
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  ORGANIC_ATOM_SET = {5, 6, 7, 8, 9, 15, 16, 17, 35, 53}
17
  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])
18
  with open('data/ceramics_list.txt', 'r') as fp:
@@ -317,7 +489,7 @@ def smiles2name(smiles):
317
  try:
318
  compounds = pcp.get_substances(smiles, namespace='smiles')
319
  # sometimes there are multiple substances, and multiple synonyms per substance
320
- allsyns = [syn for c in compounds for syn in c.iupac_name if cas not in syn]
321
  # choose the most common synonym
322
  fd = nltk.FreqDist(allsyns)
323
  name = fd.most_common(1)[0][0]
@@ -442,7 +614,7 @@ def name2iupac(string):
442
  try:
443
  compounds = pcp.get_substances(string, namespace='name')
444
  # sometimes there are multiple substances, and multiple synonyms per substance
445
- allsyns = [syn for c in compounds for syn in c.synonyms if cas not in syn]
446
  # choose the most common synonym
447
  fd = nltk.FreqDist(allsyns)
448
  name = fd.most_common(1)[0][0]
@@ -586,7 +758,7 @@ def string2density(name):
586
  if is_cas(name):
587
  mask = df_pred['CASRN'] == name
588
  if sum(mask):
589
- rho = float(df_pred[mask]['DENSITY_G/CM^3_TEST_PRED'])
590
  rho_origin = 'comptox/pred'
591
  # try to scrape from PubChem
592
  if pd.isna(rho):
@@ -1167,3 +1339,38 @@ def getLogP(cas,mol):
1167
  LogP_origin = 'rdkit/calc'
1168
  return LogP, LogP_origin
1169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  import requests
14
  import json
15
 
16
+ if 0:
17
+ ## DEBUGGING
18
+ import time
19
+ import functools
20
+ import inspect
21
+ import logging
22
+ import os
23
+ import urllib.request
24
+ import urllib.parse
25
+
26
+ try:
27
+ from flask import has_request_context, g
28
+ except Exception:
29
+ def has_request_context():
30
+ return False
31
+ g = None
32
+
33
+ TRACE_THRESHOLD = float(os.environ.get("CHEM_TRACE_THRESHOLD", "0.0"))
34
+
35
+ chemtrace_logger = logging.getLogger("chemtrace")
36
+ if not chemtrace_logger.handlers:
37
+ chemtrace_logger.setLevel(logging.INFO)
38
+
39
+ def _short(x, n=200):
40
+ s = repr(x)
41
+ return s if len(s) <= n else s[:n-3] + "..."
42
+
43
+ def _find_app_caller():
44
+ for frame in inspect.stack()[2:]:
45
+ fn = frame.filename.replace("\\", "/")
46
+ if (
47
+ "site-packages" not in fn
48
+ and "/lib/python" not in fn
49
+ and not fn.endswith("/logging/__init__.py")
50
+ ):
51
+ return {
52
+ "file": os.path.basename(frame.filename),
53
+ "func": frame.function,
54
+ "line": frame.lineno,
55
+ }
56
+ return None
57
+
58
+ def _url_info(url):
59
+ if not url:
60
+ return None
61
+ try:
62
+ parts = urllib.parse.urlsplit(str(url))
63
+ base = f"{parts.scheme}://{parts.netloc}" if parts.scheme and parts.netloc else None
64
+ return {
65
+ "url": str(url),
66
+ "base": base,
67
+ "host": parts.netloc or None,
68
+ "path": parts.path or "",
69
+ }
70
+ except Exception:
71
+ return {"url": _short(url), "base": None, "host": None, "path": None}
72
+
73
+ def _append_trace_event(event):
74
+ if has_request_context():
75
+ if getattr(g, "chem_trace", None) is None:
76
+ g.chem_trace = []
77
+ g.chem_trace.append(event)
78
+
79
+ info = event.get("target")
80
+ base = info.get("base") if isinstance(info, dict) else None
81
+ if base:
82
+ if getattr(g, "chem_bases", None) is None:
83
+ g.chem_bases = []
84
+ g.chem_bases.append(base)
85
+ else:
86
+ chemtrace_logger.info("%r", event)
87
+
88
+ def trace_call(fn):
89
+ @functools.wraps(fn)
90
+ def wrapper(*args, **kwargs):
91
+ t0 = time.perf_counter()
92
+ ok = False
93
+ err = None
94
+ try:
95
+ result = fn(*args, **kwargs)
96
+ ok = True
97
+ return result
98
+ except Exception as e:
99
+ err = f"{type(e).__name__}: {e}"
100
+ raise
101
+ finally:
102
+ dt = time.perf_counter() - t0
103
+ if dt >= TRACE_THRESHOLD:
104
+ _append_trace_event({
105
+ "kind": "app",
106
+ "fn": fn.__name__,
107
+ "secs": round(dt, 4),
108
+ "arg0": _short(args[0]) if args else None,
109
+ "ok": ok,
110
+ "err": err,
111
+ })
112
+ return wrapper
113
+
114
+ def trace_external(label, fn, formatter=None):
115
+ @functools.wraps(fn)
116
+ def wrapper(*args, **kwargs):
117
+ t0 = time.perf_counter()
118
+ ok = False
119
+ err = None
120
+ caller = _find_app_caller()
121
+ target = None
122
+ if formatter is not None:
123
+ try:
124
+ target = formatter(args, kwargs)
125
+ except Exception:
126
+ target = None
127
+ try:
128
+ result = fn(*args, **kwargs)
129
+ ok = True
130
+ return result
131
+ except Exception as e:
132
+ err = f"{type(e).__name__}: {e}"
133
+ raise
134
+ finally:
135
+ dt = time.perf_counter() - t0
136
+ if dt >= TRACE_THRESHOLD:
137
+ _append_trace_event({
138
+ "kind": "remote",
139
+ "fn": label,
140
+ "caller": caller,
141
+ "target": target,
142
+ "secs": round(dt, 4),
143
+ "ok": ok,
144
+ "err": err,
145
+ })
146
+ return wrapper
147
+
148
+ def _fmt_urlopen(args, kwargs):
149
+ url = args[0] if len(args) > 0 else kwargs.get("url")
150
+ info = _url_info(url)
151
+ if info is not None:
152
+ info["timeout"] = kwargs.get("timeout")
153
+ return info
154
+
155
+ def _fmt_requests(args, kwargs):
156
+ method = args[1] if len(args) > 1 else kwargs.get("method")
157
+ url = args[2] if len(args) > 2 else kwargs.get("url")
158
+ info = _url_info(url)
159
+ if info is not None:
160
+ info["method"] = method
161
+ info["timeout"] = kwargs.get("timeout")
162
+ return info
163
+
164
+ def _fmt_selenium_get(args, kwargs):
165
+ url = args[1] if len(args) > 1 else kwargs.get("url")
166
+ return _url_info(url)
167
+
168
+ def _fmt_pcp(args, kwargs):
169
+ query = args[0] if len(args) > 0 else kwargs.get("identifier")
170
+ namespace = args[1] if len(args) > 1 else kwargs.get("namespace")
171
+ info = _url_info(getattr(pcp, "API_BASE", None)) or {}
172
+ info.update({
173
+ "query": _short(query),
174
+ "namespace": namespace,
175
+ })
176
+ return info
177
+
178
+ def _fmt_cirpy(args, kwargs):
179
+ query = args[0] if len(args) > 0 else None
180
+ resolver = args[1] if len(args) > 1 else kwargs.get("resolver")
181
+ info = _url_info(getattr(cirpy, "API_BASE", None)) or {}
182
+ info.update({
183
+ "query": _short(query),
184
+ "resolver": resolver,
185
+ })
186
+ return info
187
+
188
  ORGANIC_ATOM_SET = {5, 6, 7, 8, 9, 15, 16, 17, 35, 53}
189
  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])
190
  with open('data/ceramics_list.txt', 'r') as fp:
 
489
  try:
490
  compounds = pcp.get_substances(smiles, namespace='smiles')
491
  # sometimes there are multiple substances, and multiple synonyms per substance
492
+ allsyns = [syn for c in compounds for syn in c.iupac_name if smiles not in syn]
493
  # choose the most common synonym
494
  fd = nltk.FreqDist(allsyns)
495
  name = fd.most_common(1)[0][0]
 
614
  try:
615
  compounds = pcp.get_substances(string, namespace='name')
616
  # sometimes there are multiple substances, and multiple synonyms per substance
617
+ allsyns = [syn for c in compounds for syn in c.synonyms if string not in syn]
618
  # choose the most common synonym
619
  fd = nltk.FreqDist(allsyns)
620
  name = fd.most_common(1)[0][0]
 
758
  if is_cas(name):
759
  mask = df_pred['CASRN'] == name
760
  if sum(mask):
761
+ rho = float(df_pred[mask]['DENSITY_G/CM^3_TEST_PRED'].iloc[0])
762
  rho_origin = 'comptox/pred'
763
  # try to scrape from PubChem
764
  if pd.isna(rho):
 
1339
  LogP_origin = 'rdkit/calc'
1340
  return LogP, LogP_origin
1341
 
1342
+ ### DEBUGGING
1343
+ if 1:
1344
+ ResolveChemical = trace_call(ResolveChemical)
1345
+ smiles2name = trace_call(smiles2name)
1346
+ cas2smiles = trace_call(cas2smiles)
1347
+ cas2name = trace_call(cas2name)
1348
+ name2iupac = trace_call(name2iupac)
1349
+ name2cas = trace_call(name2cas)
1350
+ name2smiles = trace_call(name2smiles)
1351
+ string2density = trace_call(string2density)
1352
+ string2mp = trace_call(string2mp)
1353
+ mol2mp = trace_call(mol2mp)
1354
+ if hasattr(pcp, "urlopen"):
1355
+ pcp.urlopen = trace_external("pubchempy.urlopen", pcp.urlopen, _fmt_urlopen)
1356
+
1357
+ if hasattr(cirpy, "urlopen"):
1358
+ cirpy.urlopen = trace_external("cirpy.urlopen", cirpy.urlopen, _fmt_urlopen)
1359
+
1360
+ pcp.get_compounds = trace_external("pcp.get_compounds", pcp.get_compounds, _fmt_pcp)
1361
+ pcp.get_substances = trace_external("pcp.get_substances", pcp.get_substances, _fmt_pcp)
1362
+ cirpy.resolve = trace_external("cirpy.resolve", cirpy.resolve, _fmt_cirpy)
1363
+ urllib.request.urlopen = trace_external("urllib.request.urlopen", urllib.request.urlopen, _fmt_urlopen)
1364
+ requests.sessions.Session.request = trace_external(
1365
+ "requests.Session.request",
1366
+ requests.sessions.Session.request,
1367
+ _fmt_requests,
1368
+ )
1369
+
1370
+ if try_dsstox:
1371
+ selenium.webdriver.Chrome.get = trace_external(
1372
+ "selenium.webdriver.Chrome.get",
1373
+ selenium.webdriver.Chrome.get,
1374
+ _fmt_selenium_get,
1375
+ )
1376
+
color2_module/templates/chemError.html CHANGED
@@ -16,9 +16,11 @@
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>
 
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 automatically identify your chemical. Please return to the previous page and try a
20
+ different identifier. You may try to manually determine the SMILES structural code for your chemical using tools like
21
+ <a href='https://cactus.nci.nih.gov/chemical/structure'>NCI/CADD Chemical Identifier Resolver</a>, <a href='https://pubchem.ncbi.nlm.nih.gov/'>PubChem</a>, or
22
+ <a href='https://webbook.nist.gov/chemistry/'>NIST Chemistry WebBook</a>.
23
  </p>
24
 
25
 
26
+ </body>
color3_module/templates/chemError.html CHANGED
@@ -16,9 +16,11 @@
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>
 
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 automatically identify your chemical. Please return to the previous page and try a
20
+ different identifier. You may try to manually determine the SMILES structural code for your chemical using tools like
21
+ <a href='https://cactus.nci.nih.gov/chemical/structure'>NCI/CADD Chemical Identifier Resolver</a>, <a href='https://pubchem.ncbi.nlm.nih.gov/'>PubChem</a>, or
22
+ <a href='https://webbook.nist.gov/chemistry/'>NIST Chemistry WebBook</a>.
23
  </p>
24
 
25
 
26
+ </body>
exposure2_module/templates/exposure2_chemError.html CHANGED
@@ -16,8 +16,10 @@
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
 
 
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 automatically identify your chemical. Please return to the previous page and try a
20
+ different identifier. You may try to manually determine the SMILES structural code for your chemical using tools like
21
+ <a href='https://cactus.nci.nih.gov/chemical/structure'>NCI/CADD Chemical Identifier Resolver</a>, <a href='https://pubchem.ncbi.nlm.nih.gov/'>PubChem</a>, or
22
+ <a href='https://webbook.nist.gov/chemistry/'>NIST Chemistry WebBook</a>.
23
  </p>
24
 
25
 
exposure3_module/exposure.py CHANGED
@@ -14,7 +14,7 @@ from rdkit.Chem import AllChem as Chem
14
  # get additional physical properties, options are: logp, rho, mp
15
  #get_properties = [] # don't get any; this breaks ceramics logic
16
  #get_properties = ['logp','rho','mp'] # get all three
17
- get_properties = ['mp'] # only get mp
18
  # show additional physical properties
19
  show_properties = False
20
  # output additional info for physical properties
 
14
  # get additional physical properties, options are: logp, rho, mp
15
  #get_properties = [] # don't get any; this breaks ceramics logic
16
  #get_properties = ['logp','rho','mp'] # get all three
17
+ get_properties = ['mp', 'rho']
18
  # show additional physical properties
19
  show_properties = False
20
  # output additional info for physical properties
exposure3_module/templates/exposure3_chemError.html CHANGED
@@ -16,8 +16,10 @@
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
 
 
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 automatically identify your chemical. Please return to the previous page and try a
20
+ different identifier. You may try to manually determine the SMILES structural code for your chemical using tools like
21
+ <a href='https://cactus.nci.nih.gov/chemical/structure'>NCI/CADD Chemical Identifier Resolver</a>, <a href='https://pubchem.ncbi.nlm.nih.gov/'>PubChem</a>, or
22
+ <a href='https://webbook.nist.gov/chemistry/'>NIST Chemistry WebBook</a>.
23
  </p>
24
 
25
 
exposure_module/templates/chemError.html CHANGED
@@ -16,9 +16,11 @@
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>
 
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 automatically identify your chemical. Please return to the previous page and try a
20
+ different identifier. You may try to manually determine the SMILES structural code for your chemical using tools like
21
+ <a href='https://cactus.nci.nih.gov/chemical/structure'>NCI/CADD Chemical Identifier Resolver</a>, <a href='https://pubchem.ncbi.nlm.nih.gov/'>PubChem</a>, or
22
+ <a href='https://webbook.nist.gov/chemistry/'>NIST Chemistry WebBook</a>.
23
  </p>
24
 
25
 
26
+ </body>
quantity_module/templates/quantity_chemError.html CHANGED
@@ -16,8 +16,10 @@
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
 
 
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 automatically identify your chemical. Please return to the previous page and try a
20
+ different identifier. You may try to manually determine the SMILES structural code for your chemical using tools like
21
+ <a href='https://cactus.nci.nih.gov/chemical/structure'>NCI/CADD Chemical Identifier Resolver</a>, <a href='https://pubchem.ncbi.nlm.nih.gov/'>PubChem</a>, or
22
+ <a href='https://webbook.nist.gov/chemistry/'>NIST Chemistry WebBook</a>.
23
  </p>
24
 
25