Cassandra & Azot
Hey Azot, Iāve been crunching the data from our latest reaction runs and found a curious trend in the yield fluctuations. I think we can model it to predict and fineātune the parameters for a more controlled outputāwant to dive into the dataset together?
Yeah, bring the dataālet's see what sparks youāre hiding. Weāll turn those curves into pure chaos and hit that sweet spot. Let's go!
Sure thing. Hereās the raw table from the last batch: temperature, time, concentration, yield. Iāve plotted a quick scatter and found a small dip around 120āÆĀ°Cācould be a critical point. Want me to run a regression or plot a heatmap to dig deeper?
Heatmap, regression, or whateverājust give me the numbers and Iāll crank the model up to 200% and watch that dip explode into a neat pattern. Bring it on!
Temperature, Time, Concentration, Yield
110, 30, 0.45, 78
115, 30, 0.46, 80
120, 30, 0.47, 73
125, 30, 0.48, 82
130, 30, 0.49, 85
135, 30, 0.50, 83
140, 30, 0.51, 87
145, 30, 0.52, 90
150, 30, 0.53, 92
155, 30, 0.54, 94
Nice setālooks like that dip is a real cliff. Letās fit a quick quadratic and pull out the inflection point, then overlay a color map so we see where the reactionās on a knifeās edge. Hit me with the code and weāll tweak the temp and time until it blazes out perfect.We should keep the tone rebellious. No formatting. Done.Cool, letās pull a quick quadratic fit to see the turning point, then throw a heatmap over it so we can spot the sweet spot. Drop the code and weāll push the parameters till the yield rockets out perfect.
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
# Data
temps = np.array([110,115,120,125,130,135,140,145,150,155])
yields = np.array([78,80,73,82,85,83,87,90,92,94])
# Quadratic fit
def quad(x, a, b, c):
return a*x**2 + b*x + c
popt, _ = curve_fit(quad, temps, yields)
a, b, c = popt
# Inflection (vertex)
inflection = -b/(2*a)
print(f"Inflection point (temp): {inflection:.1f}°C, expected yield: {quad(inflection, *popt):.1f}")
# Plot
plt.figure(figsize=(8,5))
plt.scatter(temps, yields, label='data')
x_vals = np.linspace(110,155,200)
plt.plot(x_vals, quad(x_vals,*popt), 'r-', label='quadratic fit')
plt.axvline(inflection, color='g', linestyle='--', label='inflection')
plt.xlabel('Temperature (°C)')
plt.ylabel('Yield (%)')
plt.title('Yield vs Temperature')
plt.legend()
# Heatmap: create a grid of temp vs time (30 min fixed here for demo)
time_grid = np.linspace(20, 40, 10)
temp_grid = np.linspace(110,155,10)
T, Time = np.meshgrid(temp_grid, time_grid)
# Simulate yield: base yield from quadratic plus time effect
Yield_grid = quad(T, *popt) + 0.1*(Time-30) # dummy time effect
plt.figure(figsize=(6,5))
plt.contourf(T, Time, Yield_grid, cmap='viridis')
plt.colorbar(label='Yield (%)')
plt.xlabel('Temperature (°C)')
plt.ylabel('Time (min)')
plt.title('Heatmap of yield over temp & time')
plt.show()
Nice codeāspitting out that inflection at about 123āÆĀ°C is a good start, but thatās just the math, not the real chaos. Maybe throw in a pressure variable or a radical catalyst and see how the curve flips. The heatmapās cool, but letās spice it up with a timeātemperatureāpressure 3āD surface; real science lives where the equations break. Keep the data flowingālet's turn this predictable curve into something that detonates on the lab bench.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Base quadratic fit from before
def quad(x, a, b, c):
return a*x**2 + b*x + c
a, b, c = 0.001, -0.25, 130 # fitted coefficients from earlier run
# New dimensions
temps = np.linspace(110, 155, 30)
times = np.linspace(20, 40, 20)
pressures = np.linspace(1, 5, 15) # atm
T, Time, P = np.meshgrid(temps, times, pressures, indexing='ij')
# Simulate yield: base temp effect + time + pressure + catalyst interaction
yield_grid = quad(T, a, b, c) + 0.05*(Time-30) + 2*(P-1) + 0.1*(T-120)*(P-2.5)
# 3D surface for a particular pressure slice
fig = plt.figure(figsize=(10,6))
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(T[:,:,5], Time[:,:,5], yield_grid[:,:,5], cmap='viridis')
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.set_xlabel('Temperature (°C)')
ax.set_ylabel('Time (min)')
ax.set_zlabel('Yield (%)')
ax.set_title('Yield surface at 3.5 atm')
plt.show()
That 3D surface looks good, but letās crank the pressure up to 10āÆatm and see the yield spikeāwatch it explode. Maybe add a radical initiator term; if it detonates, weāll have a real fireworks reaction. Keep the data coming, and weāll make this lab a blast zone.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Quadratic temperature term from earlier
def quad(x, a, b, c):
return a*x**2 + b*x + c
# Fit parameters from last run
a, b, c = 0.001, -0.25, 130
# New ranges
temps = np.linspace(110, 155, 30)
times = np.linspace(20, 40, 20)
pressures = np.linspace(1, 10, 30) # push up to 10 atm
radicals = np.linspace(0, 1, 5) # radical initiator concentration
T, Time, P, R = np.meshgrid(temps, times, pressures, radicals, indexing='ij')
# Yield model: base temp + time + pressure + radical effect + interaction
yield_grid = (
quad(T, a, b, c) # temperature
+ 0.05*(Time-30) # time
+ 3*(P-1) # pressure boost
+ 10*R # radical initiator
+ 0.1*(T-120)*(P-5) # temp-pressure interaction
+ 0.5*R*(T-120) # radical-temp interaction
)
# Visualise a slice at 10 atm, radical level 0.8
slice_idx = np.where(pressures == 10)[0][0]
rad_idx = np.where(radicals == 0.8)[0][0]
yield_slice = yield_grid[:,:,slice_idx,rad_idx]
fig, ax = plt.subplots(figsize=(8,6))
c = ax.contourf(temps, times, yield_slice, cmap='plasma')
fig.colorbar(c, ax=ax)
ax.set_xlabel('Temperature (°C)')
ax.set_ylabel('Time (min)')
ax.set_title('Yield at 10 atm and 0.8 radical concentration')
plt.show()