एक बिखराव की साजिश को कैसे चेतन करें?


83

मैं एक स्कैटर प्लॉट का एनीमेशन करने की कोशिश कर रहा हूं, जहां एनीमेशन के विभिन्न चरण में बिंदुओं के रंग और आकार बदलते हैं। डेटा के लिए मेरे पास दो x x मान और y मान के साथ दो बराबर ndarray है:

data.shape = (ntime, npoint)
x.shape = (npoint)
y.shape = (npoint)

अब मैं टाइप की एक स्कैटर प्लॉट करना चाहता हूं

pylab.scatter(x,y,c=data[i,:])

और इंडेक्स पर एक एनीमेशन बनाएं i। मैं यह कैसे करु?


2
मेटप्लोटलिब प्रलेखन में एक उदाहरण है: वर्षा सिमुलेशन
महत्त्व

जवाबों:


142

मान लीजिए कि आपके पास एक बिखराव की साजिश है scat = ax.scatter(...), तो आप कर सकते हैं

  • स्थिति बदलें

          scat.set_offsets(array)
    

जहाँ x और y निर्देशांक arrayका एक N x 2आकार सरणी है।

  • आकार बदलें

          scat.set_sizes(array)
    

arrayबिंदुओं में आकारों का 1D सरणी कहां है।

  • रंग बदलें

          scat.set_array(array)
    

जहां arrayमूल्यों का 1D सरणी है जिसे कॉलोर्म्ड किया जाएगा।

यहां एनीमेशन मॉड्यूल का उपयोग करके एक त्वरित उदाहरण दिया गया है ।
यह होने की तुलना में थोड़ा अधिक जटिल है, लेकिन इससे आपको कट्टर चीजों को करने के लिए एक रूपरेखा मिलनी चाहिए।

(वर्तमान संस्करणों के साथ संगत होने के लिए कोड अप्रैल 2019 को संपादित किया गया है। पुराने कोड के लिए संशोधन इतिहास देखें )

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

class AnimatedScatter(object):
    """An animated scatter plot using matplotlib.animations.FuncAnimation."""
    def __init__(self, numpoints=50):
        self.numpoints = numpoints
        self.stream = self.data_stream()

        # Setup the figure and axes...
        self.fig, self.ax = plt.subplots()
        # Then setup FuncAnimation.
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=5, 
                                          init_func=self.setup_plot, blit=True)

    def setup_plot(self):
        """Initial drawing of the scatter plot."""
        x, y, s, c = next(self.stream).T
        self.scat = self.ax.scatter(x, y, c=c, s=s, vmin=0, vmax=1,
                                    cmap="jet", edgecolor="k")
        self.ax.axis([-10, 10, -10, 10])
        # For FuncAnimation's sake, we need to return the artist we'll be using
        # Note that it expects a sequence of artists, thus the trailing comma.
        return self.scat,

    def data_stream(self):
        """Generate a random walk (brownian motion). Data is scaled to produce
        a soft "flickering" effect."""
        xy = (np.random.random((self.numpoints, 2))-0.5)*10
        s, c = np.random.random((self.numpoints, 2)).T
        while True:
            xy += 0.03 * (np.random.random((self.numpoints, 2)) - 0.5)
            s += 0.05 * (np.random.random(self.numpoints) - 0.5)
            c += 0.02 * (np.random.random(self.numpoints) - 0.5)
            yield np.c_[xy[:,0], xy[:,1], s, c]

    def update(self, i):
        """Update the scatter plot."""
        data = next(self.stream)

        # Set x and y data...
        self.scat.set_offsets(data[:, :2])
        # Set sizes...
        self.scat.set_sizes(300 * abs(data[:, 2])**1.5 + 100)
        # Set colors..
        self.scat.set_array(data[:, 3])

        # We need to return the updated artist for FuncAnimation to draw..
        # Note that it expects a sequence of artists, thus the trailing comma.
        return self.scat,


if __name__ == '__main__':
    a = AnimatedScatter()
    plt.show()

यहाँ छवि विवरण दर्ज करें

आप OSX पर और OSX बैकएंड का उपयोग कर रहे हैं, तो आप को बदलना होगा blit=Trueकरने blit=Falseमें FuncAnimationनीचे प्रारंभ। OSX बैकएंड पूरी तरह से ब्लटिंग का समर्थन नहीं करता है। प्रदर्शन भुगतना होगा, लेकिन उदाहरण को अक्षम विकलांग के साथ OSX पर सही ढंग से चलना चाहिए।


एक सरल उदाहरण के लिए, जो सिर्फ रंगों को अपडेट करता है, निम्नलिखित पर एक नज़र रखता है:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

def main():
    numframes = 100
    numpoints = 10
    color_data = np.random.random((numframes, numpoints))
    x, y, c = np.random.random((3, numpoints))

    fig = plt.figure()
    scat = plt.scatter(x, y, c=c, s=100)

    ani = animation.FuncAnimation(fig, update_plot, frames=range(numframes),
                                  fargs=(color_data, scat))
    plt.show()

def update_plot(i, data, scat):
    scat.set_array(data[i])
    return scat,

main()

हाय जो मैंने आपका पहला उदाहरण आज़माया है, लेकिन यह काम नहीं करता है जबकि दूसरा हाँ है। शायद मैं पहले विकल्प को डीबग करने की कोशिश करूंगा, इससे मुझे अपने अजगर ज्ञान को बेहतर बनाने में मदद मिलेगी। धन्यवाद
निकॉला Vianello

1
दुर्भाग्य से पहला उदाहरण मेरे लिए या तो ओएस एक्स पर matplotlib 1.3.1 का उपयोग करके प्रदर्शित नहीं होता है। मुझे लगता है कि फ्रेम में कोई बिंदु नहीं दिखाए जाते हैं। दूसरा उदाहरण काम करता है।
जोशेल

9
कैसे दुनिया में आप पता लगा कि .set_array()डॉट रंग अद्यतन करेगा ?!
लुकास

1
पहला उदाहरण काम नहीं कर रहा है आपको लाइन self.Scat.set_offsets(data[:2, :]) को बदलना होगाself.scat.set_offsets(data[:2, :].reshape(self.numpoints, 2))
AN O'Nyme

2
क्या कोई फ़ंक्शन है जो तितर बितर बिंदुओं के मार्कर को बदलता है?
कॉन्स्टैंटिनोस

13

मैंने इसे आसान बनाने के लिए सेल्यूलॉइड लिखा । संभवतः उदाहरण द्वारा दिखाना सबसे आसान है:

import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from celluloid import Camera

numpoints = 10
points = np.random.random((2, numpoints))
colors = cm.rainbow(np.linspace(0, 1, numpoints))
camera = Camera(plt.figure())
for _ in range(100):
    points += 0.1 * (np.random.random((2, numpoints)) - .5)
    plt.scatter(*points, c=colors, s=100)
    camera.snap()
anim = camera.animate(blit=True)
anim.save('scatter.mp4')

यहाँ छवि विवरण दर्ज करें

यह ArtistAnimationहुड के नीचे का उपयोग करता है । camera.snapएनीमेशन में फ़्रेम बनाने के लिए उपयोग की जाने वाली आकृति की वर्तमान स्थिति को कैप्चर करता है।

संपादित करें: यह निर्धारित करने के लिए कि मैं इसे कितनी मेमोरी का उपयोग करता हूं, मैमोरी_प्रोफाइलर के माध्यम से इसे चलाया

Line #    Mem usage    Increment   Line Contents
================================================
    11     65.2 MiB     65.2 MiB   @profile
    12                             def main():
    13     65.2 MiB      0.0 MiB       numpoints = 10
    14     65.2 MiB      0.0 MiB       points = np.random.random((2, numpoints))
    15     65.2 MiB      0.1 MiB       colors = cm.rainbow(np.linspace(0, 1, numpoints))
    16     65.9 MiB      0.6 MiB       fig = plt.figure()
    17     65.9 MiB      0.0 MiB       camera = Camera(fig)
    18     67.8 MiB      0.0 MiB       for _ in range(100):
    19     67.8 MiB      0.0 MiB           points += 0.1 * (np.random.random((2, numpoints)) - .5)
    20     67.8 MiB      1.9 MiB           plt.scatter(*points, c=colors, s=100)
    21     67.8 MiB      0.0 MiB           camera.snap()
    22     70.1 MiB      2.3 MiB       anim = camera.animate(blit=True)
    23     72.1 MiB      1.9 MiB       anim.save('scatter.mp4')

इसे संक्षेप में प्रस्तुत करने के लिए:

  • 100 प्लॉट बनाने में 1.9 MiB का इस्तेमाल किया गया।
  • एनीमेशन बनाने में 2.3 MiB का उपयोग किया गया।
  • एनिमेशन बनाने की इस पद्धति में योग में 4.2 MiB मेमोरी का उपयोग किया गया है।

1
चूंकि यह कलाकारअनिमेशन का उपयोग करता है, यह स्मृति में 100 तितर बितर भूखंडों का निर्माण करेगा, जो कि अक्षम है। केवल इसका उपयोग करें यदि प्रदर्शन आपके लिए महत्वपूर्ण नहीं है।
ImportanceOfBeingErnest

1
मेमोरी प्रोफाइलिंग एक अच्छा विचार है। क्या आपने भी ऐसा ही किया FuncAnimation? क्या अंतर हैं?
ImportanceOfBeingErnest

1
आप एनीमेशन को कैसे विचलित करते हैं (जैसा कि इसे फ़ाइल में सहेजने के लिए अपील की गई है)?
argentum2f

5

ये रही बात। मैं क्यूटी और मतलाब के एक उपयोगकर्ता के लिए इस्तेमाल किया और मैं matplotlib पर एनीमेशन प्रणाली से काफी परिचित नहीं हूं।

लेकिन मेरे पास एक ऐसा तरीका है जिससे आप किसी भी तरह का एनीमेशन बना सकते हैं, जैसे आप matlab में चाहते हैं। यह वास्तव में शक्तिशाली है। मॉड्यूल संदर्भों की जांच करने की आवश्यकता नहीं है और आप जो कुछ भी चाहते हैं उसे प्लॉट करने के लिए अच्छा है। इसलिए मुझे उम्मीद है कि यह मदद कर सकता है।

मूल विचार PyQt के अंदर समय की घटना का उपयोग करने के लिए है (मुझे यकीन है कि अजगर पर अन्य गुई प्रणाली wxPython और TraitUi की तरह एक ही आंतरिक तंत्र है एक घटना प्रतिक्रिया करने के लिए। लेकिन मुझे अभी पता नहीं है)। हर बार जब एक PyQt की टाइमर घटना होती है, तो मैं पूरे कैनवास को ताज़ा करता हूं और पूरी तस्वीर को फिर से बनाता हूं, मुझे पता है कि गति और प्रदर्शन धीरे-धीरे प्रभावित हो सकता है लेकिन यह इतना अधिक नहीं है।

यहाँ इसका एक छोटा सा उदाहरण दिया गया है:

import sys
from PyQt4 import QtGui

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

import numpy as np


class Monitor(FigureCanvas):
    def __init__(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)

        FigureCanvas.__init__(self, self.fig)
        self.x = np.linspace(0,5*np.pi,400)
        self.p = 0.0
        self.y = np.sin(self.x+self.p)


        self.line = self.ax.scatter(self.x,self.y)

        self.fig.canvas.draw()

        self.timer = self.startTimer(100)


    def timerEvent(self, evt):
        # update the height of the bars, one liner is easier
        self.p += 0.1
        self.y = np.sin(self.x+self.p)
        self.ax.cla()
        self.line = self.ax.scatter(self.x,self.y)

        self.fig.canvas.draw()



if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    w = Monitor()
    w.setWindowTitle("Convergence")
    w.show()
    sys.exit(app.exec_())

आप में ताज़ा गति समायोजित कर सकते हैं

        self.timer = self.startTimer(100)

मैं आपके जैसा हूँ जो एक एनीमेशन बनाने के लिए एनिमेटेड स्कैटर प्लॉट का उपयोग करना चाहते हैं। लेकिन मुझे अभी एक तथाकथित "सेट" फ़ंक्शन नहीं मिल रहा है। तो मैंने पूरा कैनवा रिफ्रेश कर दिया।

आशा है कि इससे सहायता मिलेगी..


बहुत अच्छे! हालाँकि मुझे self.startTimerमूल्य को समायोजित करके ताज़ा दर में कोई बदलाव नहीं मिला ... इस बारे में कोई सुझाव? (हाँ, मुझे पता है कि यह थोड़ी देर हो चुकी है ...)
एच। आरपोनन

-1

क्यों नहीं यह कोशिश करो

import numpy as np
import matplotlib.pyplot as plt

x=np.random.random()
y=np.random.random()

fig, ax = plt.subplots()
ax.scatter(x,y,color='teal')
ax.scatter(y,x,color='crimson')
ax.set_xlim([0,1])
ax.set_ylim([0,1])

for i in np.arange(50):
    x=np.random.random()
    y=np.random.random()
    bha=ax.scatter(x,y)
    plt.draw()
    plt.pause(0.5)
    bha.remove()

plt.show()

इसे क्यों ठुकरा दिया गया? क्या यह काम नहीं करता है?
शाम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.