Search code examples
pythonmanim

Why are some statements working only for the last iteration of the for loop in manim?


I am trying to create an animation where I want a list of Dots and Lines to track a value. I am using a ValueTracker object and updater methods for this purpose. Using ShowCreation, I have already added these objects to the scene. I used a for loop to add an updater for each Dot and Line in the list (both lists have same length):

 for i in range(len(x_points)):
    dots_cos[i].add_updater(
        lambda mob: mob.move_to(axes2.c2p(x_points[i], np.cos(omega.get_value()*x_points[i]))),
        # call_updater=False
        )
    dots_sin[i].add_updater(
        lambda mob: mob.move_to(axes2.c2p(x_points[i], np.sin(omega.get_value()*x_points[i]))),
        # call_updater=False
        )
    lines_cos[i].add_updater(
        lambda mob: mob.become(Line(axes2.coords_to_point(x_points[i], 0),
            axes2.coords_to_point(x_points[i], np.cos(omega.get_value()*x_points[i])), color=YELLOW)),
        # call_updater=False
        )
    lines_sin[i].add_updater(
        lambda mob: mob.become(Line(axes2.coords_to_point(x_points[i], 0),
            axes2.coords_to_point(x_points[i], np.sin(omega.get_value()*x_points[i])), color=RED)),
        # call_updater=False
        )

This did not work as intended! What happened was that only the last elements in the respective lists got an updater, and worked normally, while the rest of the elements simply disappeared from the scene! I tried running a for loop on zip(x_points, dots_cos, dots_sin, lines_cos, lines_sin), but still the same result.

Interestingly, when I tried to do the same using a while loop, instead of the last iteration of the loop, the code tried to add an updater to the last+1 iteration, so there was an IndexOutOfBounds exception thrown. Although a benign statement like a print statement worked fine in the while loop.

Also, in case it is significant, the lists of Dots and Lines are generated using a user-defined function that returns those lists.

So what is the problem here? How can the add_updater function break something so fundamental as a for loop?


Solution

  • You are suffering from a well known problem of constructing lambdas in a loop. Your solution could be:

    lambda mob, i=i:  ...