ম্যাটপ্লোটিলেবগুলিতে গতিময়ভাবে প্লট আপডেট করা হচ্ছে


114

আমি পাইথনে একটি অ্যাপ্লিকেশন দিচ্ছি যা সিরিয়াল বন্দর থেকে ডেটা সংগ্রহ করে এবং আগত সময়ের বিরুদ্ধে সংগৃহীত ডেটার গ্রাফ প্লট করে। ডেটা আসার সময়টি অনিশ্চিত। আমি ডেটা পাওয়ার সাথে সাথে প্লটটি আপডেট হওয়া চাই। আমি কীভাবে এটি করব তা অনুসন্ধান করেছি এবং দুটি পদ্ধতি খুঁজে পেয়েছি:

  1. প্লটটি সাফ করুন এবং পুনরায় সমস্ত পয়েন্টের সাথে প্লটটি আঁকুন।
  2. নির্দিষ্ট ব্যবধানের পরে প্লটটি পরিবর্তন করে এনিমেট করুন।

প্রোগ্রামটি চলমান এবং দীর্ঘকালীন ডেটা সংগ্রহ করার কারণে আমি প্রথমটিকে পছন্দ করি না (উদাহরণস্বরূপ একটি দিন) এবং প্লটটি পুনরায় আঁকানো বেশ ধীর হয়ে যাবে। দ্বিতীয়টিও উপাত্তের আগমনের সময়টি অনিশ্চিত হওয়ার কারণে পছন্দনীয় নয় এবং আমি ডেটা প্রাপ্ত হওয়ার পরে প্লটটি আপডেট করতে চাই।

এমন কোনও উপায় আছে যার মাধ্যমে আমি প্লটটি কেবলমাত্র আরও বেশি পয়েন্ট যুক্ত করে আপডেট করতে পারি কেবল যখন তথ্য প্রাপ্ত হয়?


উত্তর:


138

এমন কোনও উপায় আছে যেখানে আমি প্লটটিতে কেবলমাত্র আরও পয়েন্ট [গুলি] যোগ করে আপডেট করতে পারি ...

আপনার যে সংস্করণটি রয়েছে তার উপর নির্ভর করে ম্যাটপ্ল্লোবটিতে ডেটা অ্যানিমেট করার বিভিন্ন উপায় রয়েছে। আপনি ম্যাটপ্ল্লিটিব কুকবুকের উদাহরণগুলি দেখেছেন ? এছাড়াও ম্যাটপ্ল্লোব ডকুমেন্টেশনে আরও আধুনিক অ্যানিমেশন উদাহরণগুলি দেখুন । অবশেষে, অ্যানিমেশন এপিআই একটি ফাংশন সংজ্ঞা দেয় ফানক্যানিমেশন যা । এই ফাংশনটি কেবলমাত্র আপনার ডেটা অর্জনের জন্য ব্যবহার করা ফাংশন হতে পারে।

প্রতিটি পদ্ধতিই মূলত dataঅঙ্কিত হওয়া অবজেক্টটির সম্পত্তি নির্ধারণ করে , তাই স্ক্রিন বা চিত্র সাফ করার প্রয়োজন হয় না। dataসম্পত্তি কেবল বাড়ানো যেতে পারে তাই আপনি পূর্ববর্তী পয়েন্ট রাখতে পারবেন না এবং আপনার বাস্তব লাইন (বা ইমেজ বা যাই হোক না কেন আপনি অঙ্কন করা হয়) যোগ রাখা।

এই বলে যে আপনি বলেছেন যে আপনার ডেটা আগমনের সময়টি অনিশ্চিত, আপনার সেরা বেট সম্ভবত এমন কিছু করার জন্য:

import matplotlib.pyplot as plt
import numpy

hl, = plt.plot([], [])

def update_line(hl, new_data):
    hl.set_xdata(numpy.append(hl.get_xdata(), new_data))
    hl.set_ydata(numpy.append(hl.get_ydata(), new_data))
    plt.draw()

তারপরে আপনি যখন সিরিয়াল পোর্ট থেকে ডেটা পাবেন তখন কেবল কল করুন update_line


অবশেষে! আমি এই +1 এর উত্তর খুঁজছি :) আমরা কীভাবে প্লটটি স্বয়ংক্রিয়ভাবে পুনরুদ্ধার করব। ax.set_autoscale_on (সত্য) কাজ করছে বলে মনে হচ্ছে না।
এডওয়ার্ড নেওয়েল

13
উত্তরটি পেয়েছে: ax axrere () তারপরে ax.autoscale_view () এর পরে ডেটা আপডেট করার পরে কিন্তু plt.draw () কল করার আগে
এডওয়ার্ড

ম্যাটপ্ল্লোব কুকবুকের লিঙ্কটি ( scipy.org/Cookbook/Matplotlib/Animations ) ভাঙা মনে হচ্ছে (আমি একটি "নিষিদ্ধ" ত্রুটি পেয়েছি)
ডেভিড ডরিয়া

21
() দেখানোর জন্য কোনও কল নেই, তাই প্লটটি কখনও স্ক্রিনে উপস্থিত হয় না। যদি আমি শোতে কল করি (), এটি ব্লক করে এবং আপডেটগুলি সম্পাদন করে না। আমি কিছু অনুপস্থিত করছি? gist.github.com/daviddoria/027b5c158b6f200527a4
ডেভিড ডরিয়া


44

ফান-অ্যানিমেশন ছাড়াই এটি করার জন্য (যেমন প্লটটি তৈরি হওয়ার সময় আপনি কোডের অন্যান্য অংশগুলি কার্যকর করতে চান বা আপনি একই সাথে বেশ কয়েকটি প্লট আপডেট করতে চান), drawএকা কল করা প্লট তৈরি করে না (কমপক্ষে এর সাথে কিউটি ব্যাকএন্ড)।

নিম্নলিখিতটি আমার পক্ষে কাজ করে:

import matplotlib.pyplot as plt
plt.ion()
class DynamicUpdate():
    #Suppose we know the x range
    min_x = 0
    max_x = 10

    def on_launch(self):
        #Set up plot
        self.figure, self.ax = plt.subplots()
        self.lines, = self.ax.plot([],[], 'o')
        #Autoscale on unknown axis and known lims on the other
        self.ax.set_autoscaley_on(True)
        self.ax.set_xlim(self.min_x, self.max_x)
        #Other stuff
        self.ax.grid()
        ...

    def on_running(self, xdata, ydata):
        #Update data (with the new _and_ the old points)
        self.lines.set_xdata(xdata)
        self.lines.set_ydata(ydata)
        #Need both of these in order to rescale
        self.ax.relim()
        self.ax.autoscale_view()
        #We need to draw *and* flush
        self.figure.canvas.draw()
        self.figure.canvas.flush_events()

    #Example
    def __call__(self):
        import numpy as np
        import time
        self.on_launch()
        xdata = []
        ydata = []
        for x in np.arange(0,10,0.5):
            xdata.append(x)
            ydata.append(np.exp(-x**2)+10*np.exp(-(x-7)**2))
            self.on_running(xdata, ydata)
            time.sleep(1)
        return xdata, ydata

d = DynamicUpdate()
d()

হ্যাঁ! অবশেষে একটি সমাধান যা স্পাইডারের সাথে কাজ করে! আমি যে জিনিসটি হারিয়েছিলাম তা হ'ল gcf ()। ক্যানভাস.ফ্লুশ_ইভেন্টস () ড্র () - কমান্ডের পরে।
এনপি 8

এই দুর্দান্ত উদাহরণটির ভিত্তিতে আমি একটি ছোট পাইথন মডিউল লিখেছি যা পুনরাবৃত্তিমূলক চক্রান্ত করার অনুমতি দিয়েছিল
lorenzli

1
একটি সুন্দর উদাহরণ!
ভিভি

পরিষ্কার, সংক্ষিপ্ত, বহুমুখী, নমনীয়: এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।
পিফাব্রি

এটি একটি বৃহত্তর নোটবুকটিতে ব্যবহার করতে %matplotlib notebookআপনার ম্যাটপ্ল্লিটিব আমদানির বিবৃতি দেওয়ার পরে আপনাকে অবশ্যই ম্যাজিক কমান্ডটি যুক্ত করতে হবে ।
pfabri

3

এখানে এমন একটি উপায় যা নির্দিষ্ট সংখ্যক পয়েন্টের প্লট করার পরে পয়েন্টগুলি সরাতে দেয়:

import matplotlib.pyplot as plt
# generate axes object
ax = plt.axes()

# set limits
plt.xlim(0,10) 
plt.ylim(0,10)

for i in range(10):        
     # add something to axes    
     ax.scatter([i], [i]) 
     ax.plot([i], [i+1], 'rx')

     # draw the plot
     plt.draw() 
     plt.pause(0.01) #is necessary for the plot to update for some reason

     # start removing points if you don't want all shown
     if i>2:
         ax.lines[0].remove()
         ax.collections[0].remove()

2

আমি জানি আমি এই প্রশ্নের উত্তর দিতে দেরি করেছি, তবে আপনার ইস্যুটির জন্য আপনি "জয়স্টিক" প্যাকেজটি সন্ধান করতে পারেন। আমি সিরিয়াল বন্দর থেকে ডেটা স্ট্রিম প্লট করার জন্য এটি ডিজাইন করেছি, তবে এটি কোনও প্রবাহের জন্য কাজ করে। এটি ইন্টারেক্টিভ পাঠ্য লগিং বা চিত্র প্লট করার জন্য (গ্রাফ প্লটিংয়ের পাশাপাশি) মঞ্জুরি দেয়। একটি পৃথক থ্রেডে আপনার নিজের লুপগুলি করার দরকার নেই, প্যাকেজটি এটি যত্ন করে, কেবল আপনার পছন্দ আপডেটের ফ্রিকোয়েন্সি দিন। প্লাস করার সময় টার্মিনাল পর্যবেক্ষণ কমান্ডগুলির জন্য উপলব্ধ থাকে। দেখুন http://www.github.com/ceyzeriat/joystick/ বা https://pypi.python.org/pypi/joystick (ব্যবহারের পিপ ইনস্টল করতে জয়স্টিক ইনস্টল)

কেবলমাত্র নীচের কোডটিতে সিরিয়াল পোর্ট থেকে আপনার বাস্তব তথ্য পয়েন্ট দ্বারা np.random.random () প্রতিস্থাপন করুন:

import joystick as jk
import numpy as np
import time

class test(jk.Joystick):
    # initialize the infinite loop decorator
    _infinite_loop = jk.deco_infinite_loop()

    def _init(self, *args, **kwargs):
        """
        Function called at initialization, see the doc
        """
        self._t0 = time.time()  # initialize time
        self.xdata = np.array([self._t0])  # time x-axis
        self.ydata = np.array([0.0])  # fake data y-axis
        # create a graph frame
        self.mygraph = self.add_frame(jk.Graph(name="test", size=(500, 500), pos=(50, 50), fmt="go-", xnpts=10000, xnptsmax=10000, xylim=(None, None, 0, 1)))

    @_infinite_loop(wait_time=0.2)
    def _generate_data(self):  # function looped every 0.2 second to read or produce data
        """
        Loop starting with the simulation start, getting data and
    pushing it to the graph every 0.2 seconds
        """
        # concatenate data on the time x-axis
        self.xdata = jk.core.add_datapoint(self.xdata, time.time(), xnptsmax=self.mygraph.xnptsmax)
        # concatenate data on the fake data y-axis
        self.ydata = jk.core.add_datapoint(self.ydata, np.random.random(), xnptsmax=self.mygraph.xnptsmax)
        self.mygraph.set_xydata(t, self.ydata)

t = test()
t.start()
t.stop()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.