MLP224: point_from_proportion on a confirmed-long path in a per-frame callback¶
qual reports MLP224 when point_from_proportion runs inside a
per-frame callback on a receiver whose point count is confirmed
large: every call measures the length of each curve in the path to build
an arc-length table before locating the sample, and per frame on a long
path that repeated measurement dominates.
- Default severity:
info - Minimum confidence:
high - Implementation phase:
3 - Fix: none
- Supersedes:
MLP203(the generic family-walk rule routespoint_from_proportionentries here and never reports them itself)
Emission gate (cited in evidence): P >= 1024 (large-points-gate) —
only a proven lower bound confirms; loop-built paths widen to open
intervals and stay silent.
Scope: receiver resolution uses the updater-lambda-host contract (the
callee is exactly <param>.<method> directly inside a
Mobject.add_updater lambda), so queries against other objects inside
a callback stay silent. The catalog's general apply_function leg is
also out of scope: no fact layer proves that an apply_function
callback iterates the full point set of a specific receiver, so it is
never guessed.
Proven execution (liveness)¶
A hot context only proves the call is reachable from a per-frame entry point. The diagnostic additionally requires at least one play where the callback provably executes per frame (DESIGN 3.2/3.3):
- the registration is active at the play (registered on every path and not removed before it),
- the host is in the scene family there,
- the host is not suspended:
Animation.begin()suspends the animated mobject's updaters — recursively over its family — for the whole play (animation.py), unless the animation was constructed withsuspend_mobject_updating=False, - the play actually runs callbacks: a
play(...), or a wait that is provably dynamic (scene.pyshould_update_mobjects). A one-argument updater leaves the defaultwait()a static frame.
self.add(label); self.play(FadeIn(label), run_time=2); self.wait(3)
therefore stays silent: the only play suspends the updater and the wait
is static, so the callback runs about once — never once per frame.
Evidence lists the counted plays (execution) so the claim is
auditable; quantities sum over the proven plays only, and only-maybe
evidence (a branch-dependent registration, an unknown animation that may
suspend the host) never reaches this rule's high confidence.
Wrong¶
class Demo(Scene):
def construct(self):
anchor = Square()
path = VGroup(*many_circles) # >= 1024 points, confirmed
path.add_updater(lambda m: m.move_to(m.point_from_proportion(0.5)))
self.add(path, anchor)
self.play(FadeIn(anchor), run_time=2) # path stays live: its updater runs