Skip to content

TitrationCurve and PhScale

Cargo featurefeatures = ["chemistry"]

Titration is an acid titrated with sodium hydroxide: the acid’s concentration and volume, the base’s concentration, and a pka for a weak acid (Titration::weak) or none for a strong one (Titration::strong). ph(added) solves the charge balance exactly, so the start, the buffer region and the equivalence point all come out right: 25 mL of 0.1 M acetic acid starts at pH 2.88, is at 4.76 at half equivalence and at 8.72 at equivalence. equivalence() gives the base needed and curve(until, steps) the points.

TitrationCurve draws the curve on the axes of an Axes you show yourself (mL across, pH up). From delay the base pours in at a constant rate up to until mL over run_time seconds, with a dot at the current pH. As the pour passes them, the equivalence point is marked with guides to both axes and its pH. For a weak acid, the half-equivalence point is marked too, where the pH equals the pKa. ph_at(seconds) gives the pH at a time, for a readout or a PhScale pointer.

PhScale is the scale as 15 cells in the colours of universal indicator (indicator_color blends them), with the values and “acidic”, “neutral” and “basic” under it. Each of markers, a name and a pH, points at its place from above. They appear stagger seconds apart after delay, in two rows. A pointer marks a pH on the bar. Gallery scenes: TitrationCurve (acetic acid, with a scale following the pH) and PhScale (everyday substances).

TitrationCurve demo, first frame
TitrationCurve 6 s
PhScale demo, first frame
PhScale 3.5 s
use fframes_kit::prelude::*;
let acetic = Titration::weak(0.1, 25.0, 0.1, 4.76);
assert_eq!(acetic.equivalence(), 25.0);
assert!((acetic.ph(12.5) - 4.76).abs() < 0.01);
fn figure<'a>(ui: &mut Ui<'a, '_, '_>) -> Svgr<'a> {
let axes = Axes {
x_range: Range::new(0.0, 50.0, 10.0),
y_range: Range::new(0.0, 14.0, 2.0),
x_length: 8.0,
y_length: 4.2,
y_label: Some("pH".into()),
..ui.defaults()
};
let curve = TitrationCurve {
titration: Titration::strong(0.1, 25.0, 0.1),
axes: Some(axes.map(ui)),
delay: 0.5,
..ui.defaults()
};
let ph = curve.ph_at(ui.seconds());
let curve = ui.show(curve);
let axes = ui.show(axes);
let scale = ui.show(PhScale {
center: (0.0, -3.0),
width: 900.0,
height: 36.0,
pointer: Some(ph),
..ui.defaults()
});
svgr!(<g>{axes}{curve}{scale}</g>)
}

Components are plain structs. Set the fields you need and fill the rest with ..ui.defaults(): the defaults below come from the current theme (theme. values are fields of Theme).

The pH of a Titration as the base is added on axes (mL across, pH up): from delay over run_time seconds the base pours in at a constant rate up to until mL and the curve draws along with a dot at the current pH. When it gets there the equivalence point is marked with guides to both axes; for a weak acid the half-equivalence point too, where the pH equals the pKa. Show the axes yourself. Everything fades with parts_enter.

Field Type Default Description
titration Titration Titration::default() The acid and base being titrated, whose pH the curve follows.
axes Option<AxesMap> None The axes to draw on, mL across and pH up (c2p maps data to the canvas); None draws nothing.
until f64 50.0 Millilitres of base added when the pour ends, the right end of the curve.
delay f32 0.0 Seconds after the container’s start before the base begins to pour.
run_time f32 4.0 Seconds the pour takes, at a constant rate, from none to until mL.
labels bool true Names the equivalence point (and the half-equivalence point of a weak acid) when the curve reaches it; false for none.
color Color theme.colors.accent Colour of the curve and its moving dot.
marker_color Color theme.colors.highlight Colour of the dots on the marked points.
guide_color Color theme.colors.muted Colour of the dashed guides from a marked point to both axes.
text_color Color theme.colors.text Colour of the labels.
stroke_width f32 theme.stroke.regular Width in pixels of the curve and the guides.
parts_enter Option<FadeIn> None Fade in of the curve and its marks; None for none.
parts_exit Option<FadeOut> None Fade out of the curve and its marks before the end; None for none.

Methods:

  • fn added_at(&self, seconds: f32) -> f64: The base added by seconds, in mL.
  • fn ph_at(&self, seconds: f32) -> f64: The pH at seconds, for a PhScale pointer or a readout.

Feature chemistry · Source

The pH scale as a bar of 15 cells in the colours of universal indicator, width by height pixels around center (units of ui.space). With labels the values sit under the cells and “acidic”, “neutral” and “basic” under them. Each of markers (a name and its pH) points at its place above the bar; after delay they appear stagger seconds apart, in two rows so neighbours do not collide. A pointer marks a pH on the bar, for a value that changes. The cells draw with enter, the rest fades with parts_enter.

Field Type Default Description
center (f64, f64) (0.0, 0.0) The middle of the bar, in units of ui.space.
width f32 1350.0 Width of the bar in pixels, shared equally between the 15 cells.
height f32 70.0 Height of the bar in pixels.
markers Vec<(Cow<str>, f64)> Vec::new() Names and their pH, each pointing at its place above the bar; empty for none.
pointer Option<f64> None A pH to point at on the bar, for a value that changes; None for no pointer.
delay f32 0.0 Seconds after the container’s start before the first marker appears.
stagger f32 0.4 Seconds between one marker appearing and the next.
labels bool true Writes the pH values under the cells and “acidic”, “neutral” and “basic” under them; false for none.
text_color Color theme.colors.text Colour of the labels and marker names.
pointer_color Color theme.colors.title Colour of the pointer.
enter Option<EnterAnim> None How the cells draw; None shows them from the start.
exit Option<ExitAnim> None How the cells leave at the end of the container; None stays.
parts_enter Option<FadeIn> None Fade in of the labels, markers and pointer; None for none.
parts_exit Option<FadeOut> None Fade out of the labels, markers and pointer before the end; None for none.

Methods:

  • fn point(&self, ui: &Ui, ph: f64) -> Point: The pixel on the middle line of the bar at ph, the whole values at the cells’ middles.

Feature chemistry · Source