Vaishnav14220 commited on
Commit
c54866e
·
1 Parent(s): c15c518

Improve reaction detail plot parsing and defaults

Browse files
Files changed (1) hide show
  1. app.py +74 -21
app.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
 
3
  import os
4
  import math
 
5
  from textwrap import dedent
6
  from typing import List, Sequence, Tuple
7
 
@@ -39,6 +40,24 @@ FIELD_CHOICES = [
39
  ("Squib", FieldName.squib.value),
40
  ]
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  RELATION_CHOICES = [
43
  ("contains", Relation.contains.value),
44
  ("is", Relation.equals.value),
@@ -237,24 +256,44 @@ def fetch_detail(selected_url: str, manual_url: str):
237
  plot_fig = None
238
  if detail.datasets:
239
  dataset = detail.datasets[0]
240
- try:
241
- A_str = dataset.pre_exponential_factor or ""
242
- n_str = dataset.temperature_exponent or ""
243
- Ea_str = dataset.activation_energy or ""
244
- A = float(A_str) if A_str else 0
245
- n = float(n_str) if n_str else 0
246
- Ea = float(Ea_str) if Ea_str else 0
247
- if A > 0 and A_str and n_str: # Ensure A and n are present
248
- # Generate plot similar to generate_arrhenius_plot
249
- Tmin, Tmax, num_points = 300, 2000, 100
250
- temps = [Tmin + (Tmax - Tmin) * i / (num_points - 1) for i in range(num_points)]
251
- R = 8.314462618 # J/mol·K
252
- rates = [
253
- A * ((t / 298.0) ** n) * math.exp(-Ea / (R * t))
254
- for t in temps
255
- ]
256
- arrhenius_x = [1000.0 / t for t in temps]
257
- arrhenius_y = [math.log(k) for k in rates]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
 
259
  fig = go.Figure()
260
  fig.add_trace(
@@ -266,15 +305,29 @@ def fetch_detail(selected_url: str, manual_url: str):
266
  line=dict(color="#2563eb"),
267
  )
268
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  fig.update_layout(
270
  title=f"Arrhenius Plot for {detail.title or 'Reaction'}",
271
  xaxis_title="1000 / T (K⁻¹)",
272
  yaxis_title="ln k",
273
- height=400,
 
274
  )
275
  plot_fig = fig
276
- except (ValueError, TypeError):
277
- pass # Skip plotting if data invalid
278
 
279
  return markdown, table, plot_fig
280
 
 
2
 
3
  import os
4
  import math
5
+ import re
6
  from textwrap import dedent
7
  from typing import List, Sequence, Tuple
8
 
 
40
  ("Squib", FieldName.squib.value),
41
  ]
42
 
43
+
44
+ def _safe_float(value: str | None) -> float | None:
45
+ if value is None:
46
+ return None
47
+ text = str(value).strip()
48
+ if not text:
49
+ return None
50
+ sci_match = re.fullmatch(r"([+-]?\d+(?:\.\d+)?)\s*[x×*]\s*10\^?([+-]?\d+)", text, re.IGNORECASE)
51
+ if sci_match:
52
+ base = float(sci_match.group(1))
53
+ exponent = int(sci_match.group(2))
54
+ return base * (10 ** exponent)
55
+ cleaned = text.replace(",", "")
56
+ try:
57
+ return float(cleaned)
58
+ except ValueError:
59
+ return None
60
+
61
  RELATION_CHOICES = [
62
  ("contains", Relation.contains.value),
63
  ("is", Relation.equals.value),
 
256
  plot_fig = None
257
  if detail.datasets:
258
  dataset = detail.datasets[0]
259
+ A = _safe_float(getattr(dataset, "pre_exponential_factor", None))
260
+ n_val = _safe_float(getattr(dataset, "temperature_exponent", None))
261
+ Ea_val = _safe_float(getattr(dataset, "activation_energy", None))
262
+ if A and A > 0:
263
+ n = n_val if n_val is not None else 0.0
264
+ Ea = Ea_val if Ea_val is not None else 0.0
265
+
266
+ Tmin, Tmax = 300.0, 2000.0
267
+ range_text = getattr(dataset, "temperature_range", None)
268
+ if isinstance(range_text, str):
269
+ tokens = re.findall(r"[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?", range_text)
270
+ temp_vals = [_safe_float(tok) for tok in tokens]
271
+ temp_vals = [val for val in temp_vals if val is not None]
272
+ if len(temp_vals) >= 2:
273
+ Tmin, Tmax = min(temp_vals), max(temp_vals)
274
+ elif len(temp_vals) == 1:
275
+ center = temp_vals[0]
276
+ Tmin, Tmax = max(1.0, center - 50.0), center + 50.0
277
+ if Tmin < 1.0:
278
+ Tmin = 1.0
279
+ if Tmax <= Tmin:
280
+ Tmax = Tmin + 100.0
281
+
282
+ num_points = 120
283
+ temps = [Tmin + (Tmax - Tmin) * i / (num_points - 1) for i in range(num_points)]
284
+ R = 8.314462618 # J/mol·K
285
+ rates = [
286
+ A * ((t / 298.0) ** n) * math.exp(-Ea / (R * t))
287
+ for t in temps
288
+ ]
289
+ plot_points = [
290
+ (1000.0 / t, math.log(k))
291
+ for t, k in zip(temps, rates)
292
+ if k > 0
293
+ ]
294
+ if plot_points:
295
+ arrhenius_x, arrhenius_y = zip(*plot_points)
296
+ arrhenius_x, arrhenius_y = list(arrhenius_x), list(arrhenius_y)
297
 
298
  fig = go.Figure()
299
  fig.add_trace(
 
305
  line=dict(color="#2563eb"),
306
  )
307
  )
308
+
309
+ k_298 = _safe_float(getattr(dataset, "rate_at_298", None))
310
+ if k_298 and k_298 > 0:
311
+ fig.add_trace(
312
+ go.Scatter(
313
+ x=[1000.0 / 298.0],
314
+ y=[math.log(k_298)],
315
+ mode="markers",
316
+ name="k(298 K)",
317
+ marker=dict(size=10, color="#dc2626"),
318
+ hovertemplate="T = 298 K<br>k = %{customdata[0]:.3e}",
319
+ customdata=[[k_298]],
320
+ )
321
+ )
322
+
323
  fig.update_layout(
324
  title=f"Arrhenius Plot for {detail.title or 'Reaction'}",
325
  xaxis_title="1000 / T (K⁻¹)",
326
  yaxis_title="ln k",
327
+ height=360,
328
+ margin=dict(l=40, r=20, t=60, b=40),
329
  )
330
  plot_fig = fig
 
 
331
 
332
  return markdown, table, plot_fig
333