Matplotlib के साथ एक गैर-अवरुद्ध तरीके से प्लॉटिंग


138

मैं पिछले कुछ दिनों में नेम्पी और मैटलपोटलिब के साथ खेल रहा हूं। मुझे समस्या हो रही है कि matplotlib को ब्लॉक किए बिना फंक्शन को प्लॉट करने की कोशिश करें। मुझे पता है कि एसओ पर पहले से ही कई सूत्र हैं जो समान सवाल पूछते हैं, और मैं काफी गुगली कर रहा हूं लेकिन यह काम करने में कामयाब नहीं हुआ है।

मैंने शो (ब्लॉक = गलत) का उपयोग करने की कोशिश की है जैसा कि कुछ लोग सुझाव देते हैं, लेकिन मुझे जो भी मिलता है वह एक जमी हुई खिड़की है। यदि मैं केवल शो कॉल करता हूं (), तो परिणाम ठीक से प्लॉट किया गया है लेकिन विंडो बंद होने तक निष्पादन अवरुद्ध है। अन्य थ्रेड्स से मैंने पढ़ा है, मुझे संदेह है कि शो (ब्लॉक = गलत) काम करता है या नहीं, बैकएंड पर निर्भर करता है। क्या ये सही है? मेरा बैक एंड Qt4Agg है। क्या आप मेरे कोड को देख सकते हैं और मुझे बता सकते हैं कि क्या आप कुछ गलत देखते हैं? यहाँ मेरा कोड है। किसी भी मदद के लिए धन्यवाद।

from math import *
from matplotlib import pyplot as plt
print plt.get_backend()



def main():
    x = range(-50, 51, 1)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4

        y = [Xi**pow for Xi in x]
        print y

        plt.plot(x, y)
        plt.draw()
        #plt.show()             #this plots correctly, but blocks execution.
        plt.show(block=False)   #this creates an empty frozen window.
        _ = raw_input("Press [enter] to continue.")


if __name__ == '__main__':
    main()

पुनश्च। मैं यह कहना भूल गया कि मैं हर बार मौजूदा विंडो को अपडेट करना चाहूंगा, जिससे मैं नया निर्माण कर सकूं।


1
क्या आपने plt.ion()पहले के साथ matplotlib इंटरैक्टिव मोड की कोशिश की है plt.show()? यह तब गैर-अवरुद्ध होना चाहिए क्योंकि प्रत्येक भूखंड को एक बच्चे के धागे में रखा गया है।
ऐजेल

@Anzel मैंने अभी इसकी कोशिश की, लेकिन इससे कोई फर्क नहीं पड़ता।
23

3
आप अपनी स्क्रिप्ट कैसे चला रहे हैं? यदि मैं आपके उदाहरण कोड को टर्मिनल / कमांड प्रॉम्प्ट से चलाता हूं, तो यह ठीक काम करता है, लेकिन मुझे लगता है कि मुझे पहले से परेशानी हुई है जब मैं इस तरह की चीजों को IPython QtConsole या IDEs से करने की कोशिश कर रहा हूं।
मेरियस

1
@ मेरी आहा !! तुम सही हो। वास्तव में मैं इसे अपने आईडीई (PyCharm) के कंसोल से चला रहा हूं। इसे cmd प्रॉम्प्ट से चलाने पर, plt.show (block = False), ठीक काम करता है! अगर मैं आपसे पूछूं कि क्या आपको कोई विचार / समाधान मिला है तो क्या मैं बहुत अधिक पूछ रहा हूं? आपका बहुत बहुत धन्यवाद!
opetroch

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

जवाबों:


167

मैंने लंबे समय तक समाधान की तलाश में बिताया, और यह जवाब मिला ।

ऐसा लगता है कि, जैसे आपको (और मैं) क्या चाहते प्राप्त करने के लिए, आप के संयोजन की जरूरत है plt.ion(), plt.show()(नहीं के साथ block=False) और, सबसे महत्वपूर्ण बात, plt.pause(.001)(या जो भी समय आप चाहते हैं)। ठहराव की जरूरत है क्योंकि जीयूआई घटनाओं हुआ जबकि मुख्य कोड ड्राइंग सहित, सो रही है। यह संभव है कि यह एक सोने के धागे से समय निकालकर लागू किया जाता है, इसलिए हो सकता है कि IDE के साथ गड़बड़ हो - मुझे नहीं पता।

यहां एक कार्यान्वयन है जो मेरे लिए अजगर 3.5 पर काम करता है:

import numpy as np
from matplotlib import pyplot as plt

def main():
    plt.axis([-50,50,0,10000])
    plt.ion()
    plt.show()

    x = np.arange(-50, 51)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4
        y = [Xi**pow for Xi in x]
        plt.plot(x, y)
        plt.draw()
        plt.pause(0.001)
        input("Press [enter] to continue.")

if __name__ == '__main__':
    main()

3
आपके जवाब से मुझे एक समान समस्या को हल करने में बहुत मदद मिली जो मैं कर रहा था। पहले, मैंने इसके plt.drawबाद plt.show(block = False)काम किया था, लेकिन इसके बाद काम करना बंद कर दिया: चित्रा ने जवाब नहीं दिया, इसे बंद करने से iPython दुर्घटनाग्रस्त हो गया। मेरा समाधान हर उदाहरण को हटा रहा था plt.draw()और इसे प्रतिस्थापित कर रहा था plt.pause(0.001)। पहले की plt.show(block = False)तरह इसके बाद होने के बजाय plt.draw, यह पहले plt.ion()और बाद में था plt.show()। मेरे पास अब है, MatplotlibDeprecationWarningलेकिन इसने मुझे अपने आंकड़े देने दिए हैं, इसलिए मैं इस समाधान से खुश हूं।
ब्लू_चिप

3
ध्यान दें कि अजगर 2.7 में, आपको उपयोग करने की आवश्यकता raw_inputनहीं है inputयहां
क्रिस

वास्तव में उपयोगी वर्कअराउंड जब प्रतिक्रियाशील "चेतन" दृष्टिकोण संभव नहीं है! किसी को भी पता है कि कैसे पदावनति चेतावनी से छुटकारा पाने के लिए?
फ्रेडरिक फोर्टियर

कृपया कोई मुझे बता सकता है कि जब मैं plt.show से पहले plt.ion को जोड़ने की कोशिश करता हूं तो मुझे फ्रीजेन कमांड प्रॉम्प्ट क्यों मिलता है?
गेब्रियल अगस्टो

@GabrielAugusto मुझे यकीन नहीं है कि क्या कारण हो सकता है, और मुझे यकीन नहीं है कि आप क्या मतलब है। मैंने सिर्फ पायथन 3.6 में इस उदाहरण का परीक्षण किया और यह अभी भी काम करता है। यदि आपने समान पैटर्न का उपयोग किया है और यह जमा देता है, तो आपकी स्थापना में कुछ गड़बड़ हो सकती है। आपको यह देखना चाहिए कि क्या सामान्य प्लॉटिंग पहले काम करता है। यदि आपने कुछ अलग करने की कोशिश की है, तो टिप्पणियों में इसके बारे में बहुत कुछ नहीं है। किसी भी मामले में, आप एक अलग प्रश्न पूछने पर विचार कर सकते हैं।
krs013

23

मेरे लिए काम करने वाली एक सरल तरकीब निम्नलिखित है:

  1. शो के अंदर ब्लॉक = गलत तर्क का उपयोग करें : plt.show (ब्लॉक = गलत)
  2. .Py स्क्रिप्ट के अंत में एक और plt.show () का उपयोग करें ।

उदाहरण :

import matplotlib.pyplot as plt

plt.imshow(add_something)
plt.xlabel("x")
plt.ylabel("y")

plt.show(block=False)

#more code here (e.g. do calculations and use print to see them on the screen

plt.show()

नोट : plt.show()मेरी स्क्रिप्ट की अंतिम पंक्ति है।


7
यह (मेरे लिए, लिनक्स, एनाकोंडा, पायथन 2.7, डिफ़ॉल्ट बैकएंड पर) एक रिक्त विंडो का उत्पादन करता है, जो निष्पादन के अंत तक रिक्त रहता है, जब यह अंत में भर जाता है। निष्पादन के बीच में एक भूखंड को अपडेट करने के लिए उपयोगी नहीं है। :-(
sh37211

@ sh37211 यह सुनिश्चित न करें कि आपका लक्ष्य क्या है। कुछ मामलों में आप कुछ प्लॉट करने की कोशिश करते हैं, लेकिन प्लॉट कमांड के बाद आपके पास अन्य कमांड होते हैं, तो यह उपयोगी है क्योंकि यह आपको अन्य कमांड को निष्पादित करने और प्लॉट करने की अनुमति देता है। इस पोस्ट को इस पर और देखें: stackoverflow.com/questions/458209/… । अगर आप किसी प्लॉट को अपडेट करना चाहते हैं तो यह दूसरा तरीका होना चाहिए।
सेरालोक

17

आप एक सरणी में प्लॉट लिखकर, फिर एक अलग थ्रेड में एरे को प्रदर्शित करके ब्लॉकिंग निष्पादन से बच सकते हैं। यहां pyformulas 0.2.8 से pf.screen का उपयोग करके एक साथ भूखंडों को उत्पन्न करने और प्रदर्शित करने का एक उदाहरण है :

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

fig = plt.figure()

canvas = np.zeros((480,640))
screen = pf.screen(canvas, 'Sinusoid')

start = time.time()
while True:
    now = time.time() - start

    x = np.linspace(now-2, now, 100)
    y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x)
    plt.xlim(now-2,now+1)
    plt.ylim(-3,3)
    plt.plot(x, y, c='black')

    # If we haven't already shown or saved the plot, then we need to draw the figure first...
    fig.canvas.draw()

    image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
    image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,))

    screen.update(image)

#screen.close()

परिणाम:

साइन एनीमेशन

अस्वीकरण: मैं pyformulas के लिए अनुचर हूं।

संदर्भ: Matplotlib: प्लॉट को सुपीरियर एरे में सहेजें


9

इनमें से बहुत से उत्तर सुपर फुलाए हुए हैं और जो मैं पा सकता हूं, उसका उत्तर यह समझना मुश्किल नहीं है।

आप चाहें plt.ion()तो उपयोग कर सकते हैं, लेकिन मैंने plt.draw()केवल प्रभावी के रूप में उपयोग किया

मेरी विशिष्ट परियोजना के लिए, मैं छवियों की साजिश रच रहा हूं, लेकिन आप इसका उपयोग कर सकते हैं plot()या scatter()इसके बजाय जो भी कर सकते हैं figimage(), इससे कोई फर्क नहीं पड़ता।

plt.figimage(image_to_show)
plt.draw()
plt.pause(0.001)

या

fig = plt.figure()
...
fig.figimage(image_to_show)
fig.canvas.draw()
plt.pause(0.001)

यदि आप एक वास्तविक आकृति का उपयोग कर रहे हैं।
मैंने इसका पता लगाने के लिए @ krs013 और @Default पिक्चर के जवाबों का इस्तेमाल किया।
उम्मीद है कि यह किसी को हर एक आकृति को एक अलग धागे पर लॉन्च करने से बचाता है, या इन उपन्यासों को पढ़ने के लिए बस यह पता लगाने के लिए


3

लाइव प्लॉटिंग

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
# plt.axis([x[0], x[-1], -1, 1])      # disable autoscaling
for point in x:
    plt.plot(point, np.sin(2 * point), '.', color='b')
    plt.draw()
    plt.pause(0.01)
# plt.clf()                           # clear the current figure

यदि डेटा की मात्रा बहुत अधिक है, तो आप एक साधारण काउंटर के साथ अद्यतन दर को कम कर सकते हैं

cnt += 1
if (cnt == 10):       # update plot each 10 points
    plt.draw()
    plt.pause(0.01)
    cnt = 0

प्रोग्राम एग्जिट के बाद होल्डिंग प्लॉट

यह मेरी वास्तविक समस्या थी, जिसके लिए मुझे संतोषजनक उत्तर नहीं मिल रहा था, मैं चाहता था कि स्क्रिप्ट समाप्त होने के बाद यह बंद न हो (जैसे MATLAB),

यदि आप इसके बारे में सोचते हैं, तो स्क्रिप्ट समाप्त होने के बाद, कार्यक्रम समाप्त हो गया है और इस तरह से प्लॉट को रखने का कोई तार्किक तरीका नहीं है, इसलिए दो विकल्प हैं

  1. स्क्रिप्ट को बाहर निकलने से रोकें (जो कि plt.show () और न कि मुझे क्या चाहिए)
  2. प्लॉट को एक अलग थ्रेड पर चलाएं (बहुत जटिल)

यह मेरे लिए संतोषजनक नहीं था इसलिए मुझे बॉक्स के बाहर एक और समाधान मिला

SaveToFile और बाहरी दर्शक में देखें

इसके लिए सेविंग और व्यूइंग दोनों तेज होनी चाहिए और दर्शक को फाइल को लॉक नहीं करना चाहिए और कंटेंट को अपने आप अपडेट करना चाहिए

बचत के लिए प्रारूप का चयन

वेक्टर आधारित प्रारूप छोटे और तेज दोनों हैं

  • SVG अच्छा है, लेकिन इसके लिए अच्छा व्यूअर नहीं मिल रहा है, सिवाय वेब ब्राउजर के जो डिफ़ॉल्ट रूप से रिफ्रेश की जरूरत है
  • पीडीएफ वेक्टर प्रारूपों का समर्थन कर सकता है और हल्के दर्शक हैं जो लाइव अपडेटिंग का समर्थन करते हैं

लाइव अपडेट के साथ फास्ट लाइटवेट व्यूअर

के लिए पीडीएफ वहाँ कई अच्छे विकल्प हैं

  • Windows पर मैं SumatraPDF का उपयोग करता हूं , जो मुफ़्त, तेज़ और हल्का है (केवल मेरे मामले के लिए 1.8MB RAM का उपयोग करता है)

  • लिनक्स पर एवियन (GNOME) और ओकुलर (KDE) जैसे कई विकल्प हैं

नमूना कोड और परिणाम

किसी फ़ाइल में प्लॉटिंग आउटपुट के लिए नमूना कोड

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(2 * x)
plt.plot(x, y)
plt.savefig("fig.pdf")

पहले चलाने के बाद, ऊपर बताए गए दर्शकों में से एक में आउटपुट फ़ाइल खोलें और आनंद लें।

यहाँ SumatraPDF के साथ VSCode का स्क्रीनशॉट दिया गया है, यह प्रक्रिया अर्ध-लाइव अपडेट दर प्राप्त करने के लिए भी काफी तेज़ है (मैं time.sleep()अंतराल के बीच उपयोग करते हुए अपने सेटअप पर 10Hz के पास प्राप्त कर सकता हूं ) pyPlot, गैर-अवरुद्ध


2

इग्गी का जवाब मेरे लिए सबसे आसान था, लेकिन बाद में subplotकमांड करते समय मुझे निम्न त्रुटि हुई जो तब नहीं थी जब मैं बस था show:

MatplotlibDeprecationWarning: पिछली कुल्हाड़ियों के समान तर्कों का उपयोग करके एक कुल्हाड़ियों को जोड़ना वर्तमान में पहले के उदाहरण का पुन: उपयोग करता है। भविष्य के संस्करण में, एक नया उदाहरण हमेशा बनाया जाएगा और वापस आ जाएगा। इस बीच, इस चेतावनी को दबाया जा सकता है, और भविष्य के व्यवहार को सुनिश्चित किया गया है, प्रत्येक कुल्हाड़ी उदाहरण के लिए एक अनूठा लेबल पास करके।

इस त्रुटि से बचने के लिए, यह उपयोगकर्ता के हिट दर्ज करने के बाद साजिश को बंद (या स्पष्ट ) करने में मदद करता है ।

यहाँ कोड है कि मेरे लिए काम किया है:

def plt_show():
    '''Text-blocking version of plt.show()
    Use this instead of plt.show()'''
    plt.draw()
    plt.pause(0.001)
    input("Press enter to continue...")
    plt.close()

0

पायथन पैकेज ड्रॉवन वास्तविक समय में एक गैर अवरुद्ध तरीके से एक भूखंड को अपडेट करने की अनुमति देता है।
यह प्रत्येक फ्रेम के लिए उपाय करने के लिए उदाहरण के लिए एक वेबकैम और OpenCV के साथ भी काम करता है। मूल पोस्ट
देखें ।

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