zpl

2012-06-18 7 views
16

पर ऑटोस्केल्ड वाई अक्षों के साथ matplotlib जुड़े एक्स अक्षों को लिंक किया गया है, मैं ज़ूम के दौरान सभी "गुलाम" भूखंडों के वाई अक्षों को स्वत: सहेजने वाले लिंक (साझा) एक्स अक्षों के साथ भूखंडों का ढेर कैसे बना सकता हूं? उदाहरण के लिए:zpl

import matplotlib.pyplot as plt 
fig = plt.figure() 
ax1 = fig.add_subplot(211) 
ax2 = fig.add_subplot(212, sharex=ax1) 
ax1.plot([0,1]) 
ax2.plot([2,1]) 
plt.show() 

जब मैं AX1 में ज़ूम, इस अद्यतन करता AX2 की एक्स अक्ष के साथ-साथ (अब तक तो अच्छा है), लेकिन मैं भी अब दिखाई डेटा श्रेणी के आधार पर लपेटकर के लिए AX2 के y अक्ष चाहते । सभी ऑटोस्केल सेटिंग्स चालू हैं (जैसा डिफ़ॉल्ट है)। यह ax2 बनाने के बाद स्वचालित रूप से ऑटोस्केल सेटिंग्स को सेट करने में मदद नहीं करता:

ax2.autoscale(enable=True, axis='y', tight=True) 
ax2.autoscale_view(tight=True, scalex=False, scaley=True) 

print ax2.get_autoscaley_on() 
-> True 

क्या मुझे कुछ याद आया?

+2

वाई-अक्ष को ऑटोस्केल्ड किया जा रहा है, लेकिन ऑटोस्कलिंग डेटा की _full_ रेंज को ध्यान में रखता है, न केवल वर्तमान ज़ूम विंडो में। इस मामले में आपको चीजें (सेमी) मैन्युअल रूप से सेट करने की आवश्यकता होगी। –

+0

@ जोकिंगटन: हाँ, यही होता है। मैं तर्क दे सकता हूं कि यह व्यवहार कम विस्फोट के सिद्धांत के अनुरूप नहीं है। एक को छोड़कर "ऑटोस्केल" वर्तमान में दृश्यमान डेटा पर लागू होना चाहिए, न कि कुछ क्षेत्र दूर स्क्रीन पर।'Xlim_changed'" खोज "के लिए – Stefan

उत्तर

21

matplotlib की axes.py के गॉरी विवरणों का अध्ययन करने के बाद, ऐसा लगता है कि डेटा के दृश्य के आधार पर कुल्हाड़ियों को ऑटोस्केल करने के लिए कोई प्रावधान नहीं है, इसलिए मैं जो चाहता था उसे प्राप्त करने के लिए कोई उच्च स्तरीय तरीका नहीं है।

हालांकि, वहाँ 'xlim_changed' घटनाओं, एक एक कॉलबैक संलग्न कर सकते हैं जो करने के लिए कर रहे हैं:

import numpy as np 

def on_xlim_changed(ax): 
    xlim = ax.get_xlim() 
    for a in ax.figure.axes: 
     # shortcuts: last avoids n**2 behavior when each axis fires event 
     if a is ax or len(a.lines) == 0 or getattr(a, 'xlim', None) == xlim: 
      continue 

     ylim = np.inf, -np.inf 
     for l in a.lines: 
      x, y = l.get_data() 
      # faster, but assumes that x is sorted 
      start, stop = np.searchsorted(x, xlim) 
      yc = y[max(start-1,0):(stop+1)] 
      ylim = min(ylim[0], np.nanmin(yc)), max(ylim[1], np.nanmax(yc)) 

     # TODO: update limits from Patches, Texts, Collections, ... 

     # x axis: emit=False avoids infinite loop 
     a.set_xlim(xlim, emit=False) 

     # y axis: set dataLim, make sure that autoscale in 'y' is on 
     corners = (xlim[0], ylim[0]), (xlim[1], ylim[1]) 
     a.dataLim.update_from_data_xy(corners, ignore=True, updatex=False) 
     a.autoscale(enable=True, axis='y') 
     # cache xlim to mark 'a' as treated 
     a.xlim = xlim 

for ax in fig.axes: 
    ax.callbacks.connect('xlim_changed', on_xlim_changed) 

दुर्भाग्य से, यह एक बहुत कम स्तर हैक, जो आसानी से (लाइन्स के अलावा अन्य वस्तुओं टूट जाएगा है पलट या लॉग axes, ...)

axes.py में उच्च स्तर की कार्यक्षमता में हुक करना संभव नहीं है, क्योंकि उच्च-स्तरीय विधियां emit = false तर्क को set_xlim() पर अग्रेषित नहीं करती हैं, जो आवश्यक है set_xlim() और 'xlim_changed' कॉलबैक के बीच एक अनंत लूप दर्ज करने से बचने के लिए।

इसके अलावा, क्षैतिज रूप से फसल वाली वस्तु की ऊर्ध्वाधर सीमा निर्धारित करने के लिए कोई एकीकृत तरीका प्रतीत नहीं होता है, इसलिए axes.py में लाइन्स, पैच, संग्रह इत्यादि को संभालने के लिए अलग कोड है, जो सभी को होने की आवश्यकता होगी कॉलबैक में दोहराया गया।

किसी भी मामले में, उपरोक्त कोड मेरे लिए काम करता है, क्योंकि मेरे पास केवल मेरी साजिश में रेखाएं हैं और मैं तंग = सही लेआउट से खुश हूं। ऐसा लगता है कि axes.py में केवल कुछ बदलावों के साथ इस कार्यक्षमता को और अधिक सुंदरता से समायोजित कर सकता है।

संपादित करें:

मैं उच्च स्तर लपेटकर कार्यक्षमता में हुक करने में सक्षम नहीं होने के बारे में गलत था। एक्स और वाई को ठीक से अलग करने के लिए इसे केवल एक विशिष्ट सेट की आवश्यकता होती है। मैंने वाई में उच्च स्तरीय ऑटोस्केलिंग का उपयोग करने के लिए कोड अपडेट किया, जो इसे काफी मजबूत बनाना चाहिए। विशेष रूप से, तंग = झूठी अब काम करता है (सभी के बाद बहुत बेहतर दिखता है), और उलट/लॉग अक्ष को कोई समस्या नहीं होनी चाहिए।

एक शेष मुद्दा सभी प्रकार की वस्तुओं के लिए डेटा सीमाओं का निर्धारण है, एक बार एक विशिष्ट एक्स सीमा तक फसल हो जाता है। यह कार्यक्षमता वास्तव में अंतर्निहित matplotlib में होनी चाहिए, क्योंकि इसे रेंडरर की आवश्यकता हो सकती है (उदाहरण के लिए, उपरोक्त कोड तोड़ देगा यदि कोई ज़ूम करता है कि केवल 0 या 1 अंक स्क्रीन पर बने रहें)। विधि Axes.relim() एक अच्छे उम्मीदवार की तरह दिखता है। यदि डेटा बदल दिया गया है, तो यह डेटा सीमाओं को फिर से समझना है, लेकिन वर्तमान में केवल लाइनों और पैच को संभालता है। Xx.relim() में वैकल्पिक तर्क हो सकते हैं जो x या y में एक विंडो निर्दिष्ट करते हैं।

+0

+1। मुझे लगता है कि यह अनियंत्रित है, है ना? – bmu

+0

@bmu: हां, मैंने इसे axes.py पढ़ने के लिए एक जगह खोजने की कोशिश कर रहा है, यह अच्छी बात है कि यह वहां है, अन्यथा हमारे पास एक्सिस और चित्रा ओवरलोडिंग बहुत मजेदार होगा ... – Stefan

+0

कोई अपडेट? मुझे वही काम करने की ज़रूरत है + क्या सोच रहा था कि क्लीनर समाधान अब मौजूद है या नहीं। –