Titration curve#

The pH during the titration of a weak acid with sodium hydroxide rises in a step around the equivalence point. A logistic step on top of a constant describes the curve well enough to locate the equivalence point precisely.

import numpy as np

import fitwise as fw

rng = np.random.default_rng(7)
volume = np.linspace(0, 20, 41)  # mL
ph = 4.0 + 6.5 / (1 + np.exp(-(volume - 12.3) / 0.45)) + rng.normal(0, 0.05, volume.size)

result = fw.fit(fw.models.sigmoid + fw.models.constant, volume, ph, yerr=0.05)
print(result)
Model:      sigmoid(x; amp, cen, width) + constant(x; c)
Method:     Trust Region Reflective (scipy least_squares) (auto: nonlinear)
Converged:  yes (25 evals)
Data:       41 points, yerr given (absolute)
Start:      amp, cen, width: step heuristic · c: edge baseline

Parameter     Value   ± Std.Err    Rel.   Bounds
amp           6.509       0.018   0.3 %   –
cen         12.3037      0.0098   0.1 %   –
width        0.4602      0.0085   1.8 %   –
c             3.978       0.011   0.3 %   –

χ²/ndf = 0.673 (37 dof, p = 0.94)    R² = 0.99983    AIC = -12.5
Correlations > 0.5:  amp–c (-0.62)
Warnings:   none

The equivalence point is the midpoint of the step:

cen = result.params["cen"]
print(f"V_eq = {cen.value:.3f} ± {cen.stderr:.3f} mL")
V_eq = 12.304 ± 0.010 mL
fig, axes = result.plot()
axes[0].set_ylabel("pH")
axes[1].set_xlabel("NaOH added (mL)")
plot 06 titration
Text(0.5, 18.503588541666666, 'NaOH added (mL)')

Total running time of the script: (0 minutes 0.135 seconds)

Gallery generated by Sphinx-Gallery