5.4.18 · D1 · Coding › Scientific Computing (Python) › Animation — FuncAnimation
Screen par motion ek jhooth hai jisme tumhari aankhein phans jaati hain: ye sirf still pictures hain jo itni tezi se swap hoti hain ki brain unhe movement mein blur kar deta hai. FuncAnimation ek robot hai jo tumhara almost-identical pictures ka stack pakad ke rakhhta hai aur unhe stopwatch par swap karta hai — aur poori kala yahi hai ki har picture mein sirf ek chhoti si cheez badlo bajaaye sab kuch dobara draw karne ke.
Is page par assume kiya gaya hai ki tum kuch nahi jaante. Line line, = ax.plot([], []) padhne se pehle tumhe jaanna chahiye ki Figure , Axes , artist , set_data, generator , frame , update function , init_func, event loop , aur yahan tak ki akela trailing comma actually kya hain. Hum har ek ko ek picture se build karte hain, us order mein jahan har ek pehle wale par tikaa hota hai, aur ant mein hum sab ko real FuncAnimation(...) call mein wire karke chalate hain.
Recall Required pre-reading vs. self-contained
Ye deep dive self-contained hai: neeche har pitfall aur mechanic yahan poori tarah explain ki gayi hai. Linked notes (jaise Artists in Matplotlib , Generators in Python ) optional enrichment hain, prerequisites nahi — tum yeh page bina unhe khole khatam kar sakte ho.
Definition Imports jo is page ke har snippet mein assume hain
Neeche har code block is tarah likha gaya hai jaise ye teen lines file ke upar pehle se run ho chuki hain:
import numpy as np # gives us np.linspace, np.sin, np.pi
import matplotlib.pyplot as plt # gives us plt.subplots, plt.show
from matplotlib.animation import FuncAnimation # the star of the topic
np aur plt sirf chhote nicknames hain. Jab bhi tum plt.subplots() ya np.sin(...) dekho, yaad rakho ye do libraries se aate hain; FuncAnimation teesri line se aata hai.
Intuition Flip-book = animation
Figure dekho. Har card ek drawing hai. Dot card se card par sirf thoda sa hilta hai. Unhe, maano, 50 cards per second par flip karo aur tumhari aankhein individual cards nahi dekh sakti — wo ek uda hua dot dekhti hain. Neeche har word is flip-book ke ek hisse ka naam hai.
Cards ka stack → frames ka sequence.
Ek card → ek frame (ek still picture).
Flip karne ki speed → interval (har card kitne time tak dikhaya jaata hai).
"Card n ke liye, dot yahan rakho" ka rule → tumhara update function .
Flip karne wala robot → event loop / timer .
Is figure ko dhyaan mein rakho; har symbol iske upar map hota hai.
Kuch bhi move hone se pehle, hume koi surface chahiye jis par draw kar sakein . Matplotlib ise do nested cheezein mein split karta hai.
Definition Figure aur Axes
Ek Figure (code mein fig likhte hain) poora sheet of paper hai — outer rectangle, window, woh page jo tum file mein save karte.
Ek Axes (likha jaata hai ax) us paper ke andar ek plotting rectangle hai — woh hissa jisme x-axis, y-axis, grid, aur tumhara actual curve hota hai. Ek fig mein kai ax ho sakte hain.
Picture mein: pale outer rectangle Figure hai; tick marks wala inner boxed region Axes hai. Code
fig, ax = plt.subplots() # plt = matplotlib.pyplot (see imports above)
dono ek saath deta hai: fig = paper, ax = us par ek drawing box.
Intuition Topic ko yeh kyun chahiye
FuncAnimation ka poora point yahi hai ki usi paper ko baar baar update karo bajaaye ise phenk ke har frame ke liye naya paper khareedne ke. Toh pehle hume ek persistent fig apna banana hoga. Woh single object hi hai jise robot flip karta rehta hai.
Poori anatomy ke liye dekho Matplotlib Figure and Axes .
Tum pixels haath se nahi draw karte. Balki, matplotlib tumhe aise objects deta hai jo khud khud draw karna jaante hain . Inhe artists kehte hain.
Ek artist koi bhi drawable object hai jise matplotlib manage karta hai — ek line, ek dot, text ka tukda, grid. Jo line tum plot karte ho woh Line2D type ka artist hai. Ise ek puppet ki tarah sochho: woh apna data (apne x-values aur y-values) hold karta hai aur jab bhi kaha jaata hai khud repaint karta hai.
Jab tum likhte ho
line, = ax.plot([], [])
tum axes par ek Line2D puppet create kar rahe ho. Abhi yeh empty data ([] aur []) hold karta hai, toh kuch draw nahi karta — lekin puppet exist karta hai, bataye jaane ke liye ready ki kahan hona hai.
Intuition "Create once" kyun matter karta hai
Ek puppet jo tum ek baar banao use forever reposition kiya ja sakta hai. Agar tum har frame mein ax.plot(...) call karte, tum har baar ek naya puppet spawn karte aur purane ko kabhi nahi hatate — they pile up, memory badhti hai, aur picture purane frozen ghosts se bhid jaati hai. Toh: ek puppet, kai positions.
Line2D, markers, aur blitting ke baare mein aur padhne ke liye Artists in Matplotlib dekho.
Yeh pure topic ka sabse important verb hai.
==line.set_data(xs, ys)== existing line puppet ko batata hai: "apne purane points bhool jao, ab tumhare points xs (horizontal positions) aur ys (vertical positions) hain." Yeh puppet ko in-place mutate karta hai — same object, naya pose.
xs — x-coordinates ki sequence (left-right).
ys — matching sequence of y-coordinates (up-down).
Dono same length ke hone chahiye: point k ( x k , y k ) par hai.
Common mistake set_data ko bare number dena
Kyun sahi lagta hai: single dot ke liye tum sochte ho "iska x 5 hai, iska y 3 hai, toh dot.set_data(5, 3)."
Kyun fragile hai: set_data sequences chahta hai, akele numbers nahi. Bare scalar across versions odd raise ya behave kar sakta hai.
Fix: lists mein wrap karo — dot.set_data([5], [3]).
Intuition Topic ko set_data kyun chahiye
Flip-book ka "dot ko thoda nudge karo" step yahi hai . Har frame set_data ek baar call karta hai same puppet ko uski nayi jagah slide karne ke liye. set_data nahi, motion nahi.
Poori wave move karne ke liye hume kaafi x-points aur har ek par ek y-value chahiye.
==np.linspace(a, b, N)== a se b tak inclusive N evenly spaced numbers banata hai. np.linspace(0, 2*np.pi, 400) axes par 0 se 2 π tak march karne wale 400 points deta hai.
Yahan π (np.pi) sirf ≈ 3.14159 number hai; 2 π ≈ 6.283 sine wave ka ek full turn hai. Hum [ 0 , 2 π ] choose karte hain taaki exactly ek hump-and-trough screen par fit ho.
Wave ko travel karane ke liye, hum likhte hain np.sin(x - 0.1*frame). Subtract kyun?
Intuition Subtract karna wave ko right kyun shift karta hai
sin ( x ) ka peak wahan hota hai jahan iska input 2 π ke equal ho. sin ( x − s ) mein peak ko ab x − s = 2 π chahiye, yaani x = 2 π + s . Bada s ⇒ peak aur right mein baitha hota hai. Jaise frame badhta hai, s = 0.1 ⋅ frame badhta hai, toh har feature right slide karta hai — wave travel karti hai. Woh single minus sign poori animation hai.
Kyunki ek NumPy expression sab 400 y-values ek saath compute karta hai, hum NumPy linspace and broadcasting par lean karte hain.
Definition frame vs frames
Ek frame ek still picture hai — flip-book ka ek card.
frames (argument) woh hai jis par robot iterate karta hai yeh jaanne ke liye ki kaunse cards banana hain. Yeh ho sakta hai:
ek integer N → values 0 , 1 , 2 , … , N − 1 tumhari function ko ek ek karke feed ki jaati hain;
koi bhi iterable (list, range, ya generator ) → har item baari baari feed hota hai.
Toh jab tum likhte ho frames=200, update function ko frame = 0, phir 1, … 199 tak milta hai. Jab tum likhte ho frames=frame_gen, generator ka har yielded value frame banta hai.
Intuition Number aur generator dono allow kyun karein?
Plain count 200 perfect hai jab sirf ek counter change ho. Lekin kabhi kabhi har frame ko ek custom value chahiye hota hai (ek time t = 0.05, 0.10, …), aur unhe inline compute karna generator ke saath zyada clean hota hai. Isliye generators matter karte hain — jo force karta hai hume define karne ke ki generator kya hota hai.
Ek generator ek function hai jo ek baar return karne ki jagah ==yield== use karta hai ek value hand karne ke liye, phir pause karne ke liye , exactly yaad rakhta hua ki woh kahan tha. Dobara poochho aur woh yield ke baad se resume karta hai. Yeh values lazily produce karta hai — sirf tab jab poochha jaaye.
Figure mein, generator ek vending slot hai: har "next!" agla value pop out karta hai (t = 0.00 , phir 0.05 , phir 0.10 …) aur phir mid-code freeze ho jaata hai agli request tak.
def frame_gen ():
t = 0.0
while t < 6.28 :
yield t # hand out t, then FREEZE here
t += 0.05 # on next request, resume from here
Intuition Generators animation ke liye perfectly fit kyun hain
Robot ko sirf kabhi next frame ki value chahiye hoti hai — kabhi ek saath saari nahi. Generator exactly yahi supply karta hai, ek ek karke, zaroorat ho toh forever, bina ek giant list pre-compute kiye. Lekin is laziness ki ek cost hai: tum generator se yeh nahi poochh sakte ki "tum kitne lambe ho?" Jab tak woh ruke tab tak use pata nahi. Isliye generator-driven animation save karne ke liye save_count chahiye (§14 mein defined) — frames kitne grab karne hain iska manual cap.
Deeper mechanics: Generators in Python .
Ab show ka star. FuncAnimation khud kuch nahi draw karta — woh sirf tumhari function ko har frame mein call karta hai aur us function ko puppets reposition karne deta hai.
Definition Update function
func
==func(frame)== ek plain Python function hai tum likhte ho. Iska single argument, frame, frames se current item hai (ek integer, ya generator ki yielded value). Andar, tum (1) is frame ka data compute karte ho, (2) puppet(s) ko us data par set_data karte ho, aur (3) changed artists return karte ho (blitting ke liye chahiye — §9). Tum is function ko naam se pass karte ho FuncAnimation ko uske doosre argument ke roop mein.
Worked example Canonical update function — ek travelling wave
x = np.linspace( 0 , 2 * np.pi, 400 )
line, = ax.plot([], [], lw = 2 ) # puppet made ONCE, outside func
def update (frame): # frame = 0, 1, 2, ... fed in by FuncAnimation
y = np.sin(x - 0.1 * frame) # this card's y-values (wave shifted right)
line.set_data(x, y) # slide the SAME puppet to the new pose
return line, # tell blit what changed (1-tuple)
update kabhi tumhare dwara call nahi hota — FuncAnimation ise call karta hai, har tick mein frame hand in karta hua.
func frame kyun leta hai aur artists kyun return karta hai
Use frame is liye chahiye ki pata chale kaunsa card draw karna hai (frame 0 aur frame 50 alag dikhte hain). Yeh artists return karta hai taaki fast redraw path (blitting) ko exactly pata ho ki kya repaint karna hai. Baaki sab — timer, repainting schedule — robot ka kaam hai, tumhara nahi.
Pehle real frame se bilkul pehle, matplotlib ek jaani pehchani blank starting state chahta hai — flip-book ka cover sochho, "frame 0 se pehle" wali picture.
==init_func()== ek optional function hai jo tum likhte ho jo clean background / empty state ek baar start mein draw karta hai (aur jab repeat=True ho toh har loop mein dobara). Yeh koi frame argument nahi leta , puppets empty karta hai (jaise line.set_data([], [])), aur — func ki tarah — artists return karta hai taaki blitting ek correct background cache kar sake.
Intuition Ise kyun chahiye (especially blit ke saath)
Blitting background ko ek baar photograph ki tarah save karta hai aur moving artists ko uss par paste karta hai. Agar puppet stale data se start karta hai, woh purana drawing cached background mein bake ho jaata hai aur har frame ko haunt karta hai. init_func ek clean slate guarantee karta hai. Blit ke bina yeh optional hai; blit ke saath yeh tumhara promise hai ki "yeh correct empty starting picture hai."
Blitting = "unchanging background ko ek baar photograph ki tarah save karo, phir har frame mein sirf moving puppet repaint karo aur use uss saved photo par paste (blit) karo." Har frame mein grid, ticks, aur labels dobara draw karna skip ho jaata hai.
return kyun chahiye
Agar matplotlib sirf moving artists repaint karne wala hai, toh use batana hoga ki kaunse artists move kiye . Yahi reason hai ki func aur init_func dono ko changed artists return karne chahiye. Ek ko return karna bhool gaye, aur blit usse kabhi repaint nahi karta — woh frozen lagta hai. Agar tum ek line aur ek dot animate karte ho, return line, dot.
Har beginner ko do commas confuse karti hain. Yeh rahi, defused.
Definition Trailing comma
ax.plot(...) ek list return karta hai jisme ek line hoti hai: [Line2D]. ==line, = ax.plot(...)== likhna us single-element list ko plain variable line mein unpack karta hai. Comma kehta hai "exactly ek item expect karo aur usse bahar nikalo."
return line, ek 1-tuple (line,) banata hai — ek iterable jisme ek artist hai — kyunki blit ko iterable chahiye, akeli object nahi.
Mnemonic Comma = "yahan ek container hai"
Trailing comma hamesha ek tiny container ka matlab hai: left par yeh 1-item list ko unpack karta hai; right par yeh ek 1-item tuple pack karta hai. Same comma, opposite directions.
==interval== milliseconds (second ke hazarwe hisse) ki sankhya hai jitni der tak har frame next flip se pehle dikhaya jaata hai. Chhota interval ⇒ tez flipping ⇒ smoother/faster motion.
Frames-per-second (ek second mein kitne cards flip hote hain) hai:
FPS = interval frame ms 1000 s ms
Worked example Units padhna
interval = 20 ms/frame deta hai FPS = 20 1000 = 50 frames/s. Aur N = 200 frames ka ek poora pass T = N ⋅ interval = 200 × 20 = 4000 ms = 4 s chalta hai.
Stopwatch kaun fire karta hai? Event loop .
Event loop ek background "keep-checking" loop hai jo GUI continuously chalata hai: yeh mouse clicks, window resizes, aur timer ticks watch karta hai, jo bhi next ho use handle karta hua. Jab tum FuncAnimation banate ho, yeh is loop ke saath ek timer register karta hai jo har interval milliseconds mein fire hota hai. Har fire par loop tumhara update function call karta hai aur changed artists repaint karta hai — woh ek frame hai.
Intuition Event loop FuncAnimation ke liye kyun matter karta hai
Kyunki loop timer ticks ke beech spin karta rehta hai, yeh tumhare clicks aur drags bhi process kar sakta hai, toh window responsive rehti hai jab animation play ho rahi ho. Ek naive for-loop plt.show() ke saath andar control seize karta aur khatam hone tak window freeze kar deta. FuncAnimation deliberately flipping job is loop ko de deta hai toh woh timing ka maalik hai aur tum sirf ek frame describe karte ho. Isliye animation start nahi hoti jab tak loop actually run na ho (§13).
Dekho Event Loops / GUI backends kyun blocking loops "hung" lagte hain.
Ab har part exist karta hai. Yeh hai poori signature, phir complete runnable program jo upar har cheez use karta hai.
Definition FuncAnimation constructor
anim = FuncAnimation(fig, func, frames = None , init_func = None ,
interval = 200 , blit = False , repeat = True , save_count = None )
fig — redraw karne ke liye persistent Figure (§1).
func — tumhara update function func(frame) (§7). Required.
frames — ek int N, iterable, ya generator (§5–6).
init_func — clean-background function (§8).
interval — frames ke beech ms (§11).
blit — True = sirf returned artists repaint karo (§9).
repeat — frames khatam hone par start par wapas loop karo.
save_count — frames ka cap jo length-unknown generator save karte waqt grab hote hain (§14).
Worked example Complete travelling-wave program (copy-paste runnable)
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots() # §1: one persistent canvas
ax.set_xlim( 0 , 2 * np.pi) # set limits ONCE so blit can cache background
ax.set_ylim( - 1.1 , 1.1 )
x = np.linspace( 0 , 2 * np.pi, 400 ) # §4: the x-points
line, = ax.plot([], [], lw = 2 ) # §2/§10: puppet made ONCE, empty
def init (): # §8: clean "before frame 0"
line.set_data([], [])
return line,
def update (frame): # §7: the per-card rule
y = np.sin(x - 0.1 * frame)
line.set_data(x, y)
return line, # §9: what blit repaints
anim = FuncAnimation(fig, update, frames = 200 , init_func = init,
interval = 20 , blit = True ) # §12: wire it all
plt.show() # §13: START the event loop (blocks here)
# anim.save("wave.mp4", fps=50) # or "wave.gif" — needs ffmpeg / pillow
anim banana khud se kuch move nahi karta; yeh sirf timer register karta hai. Event loop start karna padega.
Definition Animation start karna
Script/GUI window mein : ==plt.show()== call karo. Yeh control event loop ko deta hai, jo phir timer fire karta hai aur frames drive karta hai. plt.show() block karta hai — window band karne tak chalta hai.
File mein save karne ke liye bajaaye show karne ke: ==anim.save("out.mp4", fps=50)== call karo (mp4 ke liye ffmpeg chahiye, ya .gif ke liye pillow). Save karna frames ko 1/fps seconds se space karta hai, interval ignore karta hua.
anim = ... bhool jaana
Kyun sahi lagta hai: FuncAnimation(...) animation "start" karta lagta hai, toh tum ise bare statement ki tarah likhte ho.
Kyun toot jaata hai: return hua object timer ka maalik hai . Agar kuch uska reference nahi rakhta, Python ka garbage collector ise delete kar deta hai, timer mar jaata hai, aur window blank/frozen ho jaati hai.
Fix: hamesha anim = FuncAnimation(...) likho aur anim ko plt.show() ke baad tak alive rakho.
Movie save karne ke liye tum frames ko ffmpeg (mp4) ya pillow (gif) ko dete ho. Dekho Saving figures and ffmpeg .
==save_count== maximum frames ki sankhya hai jise matplotlib grab karega jab save karta hai aisi animation jiske frames ek generator (ya unknown length ka koi iterable) hain. Kyunki ek generator yeh nahi bata sakta ki "tum kitne values yield karoge?", save_count woh number haath se supply karta hai. Is par live plt.show() playback par koi effect nahi hota — sirf anim.save(...) par.
Worked example Generator-driven frames save_count ke saath
def frame_gen (): # §6: yields custom time values, unknown length
t = 0.0
while t < 6.28 :
yield t
t += 0.05
def update (t):
line.set_data(x, np.sin(x - t))
return line,
anim = FuncAnimation(fig, update, frames = frame_gen,
init_func = init, interval = 30 , blit = True ,
save_count = 200 ) # grab at most 200 frames when saving
anim.save( "wave.mp4" , fps = 30 )
Yahan frame_gen lagbhag 6.28/0.05 ≈ 126 values yield karta hai, toh save_count=200 ek safe upper cap hai — matplotlib tab rukta hai jab generator exhaust ho ya cap hit ho, jo pehle aaye.
Intuition Sirf saving ke liye kyun?
Live playback bas generator se agla value maangta rehta hai jab tak woh ruke — use kabhi total ki zaroorat nahi. Lekin saving ko pehle se finite reel of frames allocate/encode karni hoti hai, toh use ek promised count chahiye. save_count woh promise hai.
Figure and Axes - the canvas
set_data - move the puppet
update func - one frame rule
Generators - yield values
init_func - clean background
Blitting - return artists
anim.save via ffmpeg and save_count
Figure aur Axes mein kya fark hai? Figure = poora sheet/window; Axes = uske andar ek plotting rectangle (ticks aur grid ke saath).
Artist kya hota hai, aur plotted line kis type ki hoti hai? Ek self-drawing object jise matplotlib manage karta hai; plotted line ek Line2D hoti hai.
line.set_data(xs, ys) kya karta hai?Existing line ko in-place naye x/y points par mutate karta hai — same puppet, naya pose.
ax.plot ko update function ke bahar EK BAAR kyun call karein?Ek artist ko set_data se reuse karne ke liye; ise per frame call karne se naye artists pile up hote hain aur blit toot jaata hai.
np.linspace(0, 2*np.pi, 400) kya produce karta hai?0 se 2π tak inclusive 400 evenly spaced numbers.
np.sin(x - 0.1*frame) wave ko right kyun move karta hai?Bada shift peak (input = π/2) ko bade x par push karta hai, toh features right slide karte hain.
Generator kya hai aur yield kya karta hai? Ek function jo ek value hand back karta hai phir pause karta hai, agli request par resume karta hua.
Update function func kya hai aur iska argument kya hai? Ek function jo tum likhte ho jo current frame leta hai, set_data se puppets reposition karta hai, aur changed artists return karta hai.
init_func kis kaam aata hai, aur woh kaunsa argument leta hai?Yeh frame 0 se pehle clean empty background draw karta hai; koi frame argument nahi leta aur artists return karta hai.
FuncAnimation ka doosra positional argument kya hai?func, tumhara update function.
interval=20 ms ko FPS mein convert karo.1000/20 = 50 FPS.
Per-frame timer kaun fire karta hai? GUI event loop, jo window ko bhi responsive rakhta hai.
Screen par animation actually START kaise karte ho? plt.show() call karo, jo event loop chalata hai (aur window band hone tak block karta hai).
blit=True ke saath, func (aur init_func) ko kya return karna chahiye?Changed artists ka ek iterable, jaise return line,.
line, = ax.plot(...) mein trailing comma kya karta hai?ax.plot return karne wali single-element list ko line mein unpack karta hai.
anim = FuncAnimation(...) kyun rakhna zaroori hai?Warna yeh garbage-collect ho jaata hai, timer ruk jaata hai, aur animation freeze/blank ho jaati hai.
save_count kis kaam aata hai?Generator-driven animation SAVE karte waqt kitne frames grab karne hain iska cap; live playback ke dauran ignore hota hai.
Animation — FuncAnimation — woh parent topic jiske liye yeh page tumhe prepare karta hai.
Matplotlib Figure and Axes — fig/ax canvas.
Artists in Matplotlib — Line2D, set_data, blitting.
Generators in Python — frames ke peeche yield machine.
Event Loops / GUI backends — woh timer jo har frame fire karta hai.
NumPy linspace and broadcasting — per-frame arrays banana.
Saving figures and ffmpeg — mp4/gif mein export karna.