ম্যাটপ্লটলিবের সাথে চক্রান্ত করা এত ধীর কেন?


101

আমি বর্তমানে বিভিন্ন অজগর প্লট করা লাইব্রেরি মূল্যায়ন করছি। এই মুহূর্তে আমি ম্যাটপ্ল্লিটিব চেষ্টা করছি এবং আমি অভিনয়টি থেকে বেশ হতাশ। নিম্নলিখিত উদাহরণটি সায়পাই উদাহরণগুলি থেকে পরিবর্তিত হয়েছে এবং আমাকে প্রতি সেকেন্ডে মাত্র ~ 8 ফ্রেম দেয়!

এটির গতি বাড়ানোর কোনও উপায় বা আমার কি অন্য একটি প্লট করা লাইব্রেরি বাছাই করা উচিত?

from pylab import *
import time

ion()
fig = figure()
ax1 = fig.add_subplot(611)
ax2 = fig.add_subplot(612)
ax3 = fig.add_subplot(613)
ax4 = fig.add_subplot(614)
ax5 = fig.add_subplot(615)
ax6 = fig.add_subplot(616)

x = arange(0,2*pi,0.01)
y = sin(x)
line1, = ax1.plot(x, y, 'r-')
line2, = ax2.plot(x, y, 'g-')
line3, = ax3.plot(x, y, 'y-')
line4, = ax4.plot(x, y, 'm-')
line5, = ax5.plot(x, y, 'k-')
line6, = ax6.plot(x, y, 'p-')

# turn off interactive plotting - speeds things up by 1 Frame / second
plt.ioff()


tstart = time.time()               # for profiling
for i in arange(1, 200):
    line1.set_ydata(sin(x+i/10.0))  # update the data
    line2.set_ydata(sin(2*x+i/10.0))
    line3.set_ydata(sin(3*x+i/10.0))
    line4.set_ydata(sin(4*x+i/10.0))
    line5.set_ydata(sin(5*x+i/10.0))
    line6.set_ydata(sin(6*x+i/10.0))
    draw()                         # redraw the canvas

print 'FPS:' , 200/(time.time()-tstart)

নিম্নলিখিতটি প্রাসঙ্গিক হতে পারে: স্ট্যাকওভারফ্লো.com
প্রশ্নগুলি

4
@ অ্যাক্স - গ্ল্যাম্পি কেবলমাত্র সেই উদাহরণটিতেই সহায়তা করেছিলেন কারণ তিনি চিত্রের ডেটা দ্রুত প্রদর্শনের সাথে সম্পর্কিত ছিলেন। এটি এই ক্ষেত্রে সাহায্য করবে না।
জো কিংটন

4
ব্যাকএন্ড পরিবর্তন করার চেষ্টা করুন। আমার উত্তর দেখুন: stackoverflow.com/a/30655528/2066079 । অথবা ব্যাক-এন্ডের সম্পর্কে এই FAQ: matplotlib.org/faq/usage_faq.html#what-is-a-backend
dberm22

উত্তর:


116

প্রথমে, (যদিও এটি কিছুতেই পারফরম্যান্স পরিবর্তন করবে না) আপনার কোড সাফ করার বিষয়টি বিবেচনা করুন, এর অনুরূপ:

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

x = np.arange(0, 2*np.pi, 0.01)
y = np.sin(x)

fig, axes = plt.subplots(nrows=6)
styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
lines = [ax.plot(x, y, style)[0] for ax, style in zip(axes, styles)]

fig.show()

tstart = time.time()
for i in xrange(1, 20):
    for j, line in enumerate(lines, start=1):
        line.set_ydata(np.sin(j*x + i/10.0))
    fig.canvas.draw()

print 'FPS:' , 20/(time.time()-tstart)

উপরের উদাহরণ সহ, আমি প্রায় 10fps পেতে।

আপনার সঠিক ব্যবহারের ক্ষেত্রে নির্ভর করে কেবল একটি দ্রষ্টব্য নোট, ম্যাটপ্ল্লোলিব দুর্দান্ত পছন্দ নাও হতে পারে। এটি রিয়েল-টাইম প্রদর্শন নয়, প্রকাশনার-মানের পরিসংখ্যানগুলির দিকে ভিত্তি করে।

তবে এই উদাহরণটি গতিময় করতে আপনি অনেক কিছুই করতে পারেন।

এটি যতটা ধীর হয় তার দুটি প্রধান কারণ রয়েছে।

1) কলিং সবকিছুfig.canvas.draw() redraws । এটা তোমার বাধা। আপনার ক্ষেত্রে, আপনাকে অক্ষগুলির সীমানা, টিক লেবেল ইত্যাদির মতো জিনিসগুলি আবার আঁকার দরকার নেই

2) আপনার ক্ষেত্রে, প্রচুর টিক লেবেল সহ প্রচুর সাবপ্লট রয়েছে। এগুলি আঁকতে দীর্ঘ সময় নেয়।

এই উভয় blitting ব্যবহার করে স্থির করা যেতে পারে।

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

তবে আপনি কী করছেন সে সম্পর্কে কিছুটা না জেনে আমি আপনাকে সেখানে সহায়তা করতে পারি না।

তবুও, এটি করার একটি গুই-নিরপেক্ষ উপায় রয়েছে যা এখনও যুক্তিসঙ্গতভাবে দ্রুত।

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

x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)

fig, axes = plt.subplots(nrows=6)

fig.show()

# We need to draw the canvas before we start animating...
fig.canvas.draw()

styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
def plot(ax, style):
    return ax.plot(x, y, style, animated=True)[0]
lines = [plot(ax, style) for ax, style in zip(axes, styles)]

# Let's capture the background of the figure
backgrounds = [fig.canvas.copy_from_bbox(ax.bbox) for ax in axes]

tstart = time.time()
for i in xrange(1, 2000):
    items = enumerate(zip(lines, axes, backgrounds), start=1)
    for j, (line, ax, background) in items:
        fig.canvas.restore_region(background)
        line.set_ydata(np.sin(j*x + i/10.0))
        ax.draw_artist(line)
        fig.canvas.blit(ax.bbox)

print 'FPS:' , 2000/(time.time()-tstart)

এটি আমাকে 200fps দেয়।

এটিকে কিছুটা সুবিধাজনক করার জন্য animationsম্যাটপ্লটলিবের সাম্প্রতিক সংস্করণগুলির একটি মডিউল রয়েছে।

উদাহরণ হিসাবে:

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

x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)

fig, axes = plt.subplots(nrows=6)

styles = ['r-', 'g-', 'y-', 'm-', 'k-', 'c-']
def plot(ax, style):
    return ax.plot(x, y, style, animated=True)[0]
lines = [plot(ax, style) for ax, style in zip(axes, styles)]

def animate(i):
    for j, line in enumerate(lines, start=1):
        line.set_ydata(np.sin(j*x + i/10.0))
    return lines

# We'd normally specify a reasonable "interval" here...
ani = animation.FuncAnimation(fig, animate, xrange(1, 200), 
                              interval=0, blit=True)
plt.show()

আপনার কোডটি আসলেই খুব দ্রুত, তবে আমি প্রতি অক্ষরে 2000 লাইন দিয়ে শেষ করছি! কোনওভাবে "line.set_ydata" আপডেট করার পরিবর্তে একটি নতুন লাইন তৈরি করে - বা ব্যাকগ্রাউন্ডটি কেবল সাফ করা হচ্ছে না? এছাড়াও, আপনার সংস্করণটি এত দ্রুত কেন? আপনি কেবল "অঙ্কন ()" বাদ দিয়েছেন এবং এটিকে "ax.draw_artist" দিয়ে প্রতিস্থাপন করেছেন?
memyself নিজে

কোন উদাহরণে? (আমি সেগুলি পরীক্ষা করেছি, তবে এটি উত্তরের ভুল সংস্করণটিকে অনুলিপি করে আটকানো সম্ভব)) এছাড়াও, ম্যাটপ্ললিটবের কোন সংস্করণ আপনি ব্যবহার করছেন?
জো কিংটন

4
ফলাফলের চিত্রটির এখানে একটি লিঙ্ক রয়েছে i.imgur.com/aBRFz.png এটি আমার গ্রাফিক্স কার্ডের কারণে তৈরি কোনও শিল্পকর্ম হতে পারে?
memyself নিজে

7
I.imgur.com/aBRFz.png এ আমি নিজে যা দেখছিলাম তা আমি দেখতে পাচ্ছিলাম যতক্ষণ না আমি ডুমুর.শো () এর নীচে ব্যাকগ্রাউন্ড ক্যাপচারটি সরিয়ে নিয়েছি।
মাইকেল ব্রাউন 18'13

4
দুর্দান্ত, তবে সময়ের সাথে সাথে animationপ্লটটি আপডেট করার কথা মনে হচ্ছে , intervalনতুন ডেটা প্রস্তুত হওয়ার সময় আমি যদি এটি আপডেট করতে চাই তবে কী হবে?
অ্যালকোট

31

ম্যাটপ্লটলিব দুর্দান্ত প্রকাশনা-মানের গ্রাফিক্স তৈরি করে তবে গতির পক্ষে খুব ভালভাবে অনুকূল হয় না। বিভিন্ন ধরণের পাইথন প্লট করার প্যাকেজ রয়েছে যা গতির সাথে বিবেচনা করে তৈরি করা হয়েছে:


4
আমি রিয়েল টাইম স্ট্রিম ডেটার জন্য পুরোপুরি পাইক্টগ্রাফ.আর / ডকুমেন্টেশন উপভোগ করি । দুর্দান্ত কাজ luke
qrtLs

11

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

যাইহোক, নন-জিইউআই-নিরপেক্ষ (জিইউআই-বায়াসড?) পদ্ধতির চক্রান্ত দ্রুত করার চাবিকাঠি। অন্য কথায়, গতির প্লট করার জন্য ব্যাকএন্ড অত্যন্ত গুরুত্বপূর্ণ।

ম্যাটপ্ল্লোলিব থেকে অন্য কিছু আমদানির আগে এই দুটি লাইন রাখুন:

import matplotlib
matplotlib.use('GTKAgg') 

অবশ্যই এর পরিবর্তে বিভিন্ন বিকল্প ব্যবহার করা যেতে পারে GTKAggতবে আগে উল্লিখিত কুকবুক অনুসারে এটি ছিল দ্রুততম। আরও বিকল্পের জন্য ব্যাকেন্ডের লিঙ্কটি দেখুন।


এটি কেবল উইন্ডোতে কাজ করে, আপনি কি এটি ম্যাকের সাথে কাজ করার কোনও উপায় জানেন। এটি উইন্ডোজ নির্দিষ্ট হওয়ার কারণটি হচ্ছে পাইগটেক উইন্ডোজ নির্দিষ্ট
ব্যবহারকারী 308827

4
pygtk উইন্ডোজ নির্দিষ্ট নয়। আসলে, এটি উইন্ডোজের অধীনে কাজ করার জন্য একটি বিশাল বেদনা (এটি যদি সম্ভব হয় তবে আমি ছেড়ে দিয়েছি)
জোসেফ রেডফার্ন

7

জো কিংটনের প্রস্তাবিত প্রথম সমাধানের জন্য (.কপি_ফ্রম_বক্স এবং .ড্রে_আর্টিস্ট এবং ক্যানভাস.ব্লিট), ডুমুরআল্ক। ক্যানভাস.ড্রই () লাইনের পরে আমাকে ব্যাকগ্রাউন্ডগুলি ক্যাপচার করতে হয়েছিল , অন্যথায় পটভূমির কোনও প্রভাব ছিল না এবং আমি একই ফলাফল পেয়েছি তুমি উল্লেখ করেছিলে. যদি আপনি এটি fig.show () পরে রাখেন তবে এটি মাইকেল ব্রাউন দ্বারা প্রস্তাবিত হিসাবে এখনও কাজ করে না।

সুতরাং কেবল ক্যানভাসের পরে ব্যাকগ্রাউন্ড লাইন রাখুন .ড্র ():

[...]
fig.show()

# We need to draw the canvas before we start animating...
fig.canvas.draw()

# Let's capture the background of the figure
backgrounds = [fig.canvas.copy_from_bbox(ax.bbox) for ax in axes]

4
আপনার পৃথক উত্তর হিসাবে পোস্ট করার পরিবর্তে কেবল তার উত্তরটি সম্পাদনা করা উচিত
এন্ডোলিথ

1

এটি আপনার অনেকের ক্ষেত্রেই প্রযোজ্য নয়, তবে আমি সাধারণত লিনাক্সের অধীনে আমার কম্পিউটারগুলি পরিচালনা করি, তাই ডিফল্টরূপে আমি আমার ম্যাটপ্ল্লিটিব প্লটগুলিকে পিএনজি এবং এসভিজি হিসাবে সংরক্ষণ করি। এটি লিনাক্সের অধীনে সূক্ষ্মভাবে কাজ করে তবে আমার উইন্ডোজ 7 ইনস্টলেশন [পাইথনের অধীনে মিকটেক্স (x, y) বা অ্যানাকোন্ডা] অসহনীয়ভাবে ধীর হয়ে গেছে, তাই আমি এই কোডটি যুক্ত করার চেষ্টা করেছি এবং জিনিসগুলি আবার সেখানে কাজ করবে:

import platform     # Don't save as SVG if running under Windows.
#
# Plot code goes here.
#
fig.savefig('figure_name.png', dpi = 200)
if platform.system() != 'Windows':
    # In my installations of Windows 7, it takes an inordinate amount of time to save
    # graphs as .svg files, so on that platform I've disabled the call that does so.
    # The first run of a script is still a little slow while everything is loaded in,
    # but execution times of subsequent runs are improved immensely.
    fig.savefig('figure_name.svg')
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.