2013-02-23 15 views
13

मैं पाइथन में Matplotlib का उपयोग कर कुछ 3 डी सतह भूखंड कर रहा हूं और एक कष्टप्रद घटना देखी है। मैं दृष्टिकोण (कैमरा स्थान) कैसे सेट करता हूं, इस पर निर्भर करता है कि लंबवत (जेड) धुरी बाएं और दाएं तरफ के बीच चलता है। यहां दो उदाहरण दिए गए हैं: Example 1, Axis left, Example 2, Axis right। पहले उदाहरण में ax.view_init (25, -135) है जबकि दूसरे में ax.view_init (25, -45) है।3 डी प्लॉट (Matplotlib) के लंबवत (जेड) अक्ष की स्थिति बदल रहा है?

मैं दृष्टिकोण को समान रखना चाहता हूं (डेटा देखने का सबसे अच्छा तरीका)। अक्ष को एक तरफ या दूसरे को मजबूर करने का कोई तरीका है?

धन्यवाद!

उत्तर

9

मुझे कुछ इसी तरह की आवश्यकता थी: दोनों तरफ ज़ैक्सिस खींचना। @crayzeewulf से जवाब देने के लिए धन्यवाद मैं (, के लिए छोड़ दिया righ, या दोनों पक्षों) वैकल्पिक हल निम्नलिखित के लिए आया था:

enter image description here

पहले भूखंड अपने 3 डी के रूप में आप की जरूरत है, तो इससे पहले कि आप show() फोन एक साथ Axes3D लपेट रैपर वर्ग जो draw() विधि को ओवरराइड करता है।

द रैपर क्लास कॉल केवल कुछ विशेषताओं की दृश्यता को झूठी पर सेट करता है, यह स्वयं को आकर्षित करता है और अंततः संशोधित योजनाओं के साथ ज़ैक्सिस खींचता है। यह रैपर वर्ग आपको बाईं ओर, दोनों तरफ या दोनों तरफ ज़ैक्सिस खींचने की अनुमति देता है।

import matplotlib 
matplotlib.use('QT4Agg') 
import matplotlib.pyplot as plt 
from mpl_toolkits.mplot3d import axes3d 

class MyAxes3D(axes3d.Axes3D): 

    def __init__(self, baseObject, sides_to_draw): 
     self.__class__ = type(baseObject.__class__.__name__, 
           (self.__class__, baseObject.__class__), 
           {}) 
     self.__dict__ = baseObject.__dict__ 
     self.sides_to_draw = list(sides_to_draw) 
     self.mouse_init() 

    def set_some_features_visibility(self, visible): 
     for t in self.w_zaxis.get_ticklines() + self.w_zaxis.get_ticklabels(): 
      t.set_visible(visible) 
     self.w_zaxis.line.set_visible(visible) 
     self.w_zaxis.pane.set_visible(visible) 
     self.w_zaxis.label.set_visible(visible) 

    def draw(self, renderer): 
     # set visibility of some features False 
     self.set_some_features_visibility(False) 
     # draw the axes 
     super(MyAxes3D, self).draw(renderer) 
     # set visibility of some features True. 
     # This could be adapted to set your features to desired visibility, 
     # e.g. storing the previous values and restoring the values 
     self.set_some_features_visibility(True) 

     zaxis = self.zaxis 
     draw_grid_old = zaxis.axes._draw_grid 
     # disable draw grid 
     zaxis.axes._draw_grid = False 

     tmp_planes = zaxis._PLANES 

     if 'l' in self.sides_to_draw : 
      # draw zaxis on the left side 
      zaxis._PLANES = (tmp_planes[2], tmp_planes[3], 
          tmp_planes[0], tmp_planes[1], 
          tmp_planes[4], tmp_planes[5]) 
      zaxis.draw(renderer) 
     if 'r' in self.sides_to_draw : 
      # draw zaxis on the right side 
      zaxis._PLANES = (tmp_planes[3], tmp_planes[2], 
          tmp_planes[1], tmp_planes[0], 
          tmp_planes[4], tmp_planes[5]) 
      zaxis.draw(renderer) 

     zaxis._PLANES = tmp_planes 

     # disable draw grid 
     zaxis.axes._draw_grid = draw_grid_old 

def example_surface(ax): 
    """ draw an example surface. code borrowed from http://matplotlib.org/examples/mplot3d/surface3d_demo.html """ 
    from matplotlib import cm 
    import numpy as np 
    X = np.arange(-5, 5, 0.25) 
    Y = np.arange(-5, 5, 0.25) 
    X, Y = np.meshgrid(X, Y) 
    R = np.sqrt(X**2 + Y**2) 
    Z = np.sin(R) 
    surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) 

if __name__ == '__main__': 
    fig = plt.figure(figsize=(15, 5)) 
    ax = fig.add_subplot(131, projection='3d') 
    ax.set_title('z-axis left side') 
    ax = fig.add_axes(MyAxes3D(ax, 'l')) 
    example_surface(ax) # draw an example surface 
    ax = fig.add_subplot(132, projection='3d') 
    ax.set_title('z-axis both sides') 
    ax = fig.add_axes(MyAxes3D(ax, 'lr')) 
    example_surface(ax) # draw an example surface 
    ax = fig.add_subplot(133, projection='3d') 
    ax.set_title('z-axis right side') 
    ax = fig.add_axes(MyAxes3D(ax, 'r')) 
    example_surface(ax) # draw an example surface 
    plt.show() 
+0

क्या आप वास्तविक सतह के साथ उदाहरण अपडेट कर सकते हैं? मुझे इसे काम करने में परेशानी हो रही है। – pyCthon

+1

जब मैं 'अंजीर' http://imgur.com/VJLTTTH – pyCthon

+1

@pyCthon सेट करने के बाद साजिश जोड़ता हूं तो मुझे यह मिलता है: उदाहरण के मेरे अपडेट को देखें। मैंने http://matplotlib.org/examples/mplot3d/surface3d_demo.html से उधारित कोड के साथ सतह खींचने के लिए एक फ़ंक्शन जोड़ा है। – wolfrevo

5

जैसा कि ओपी द्वारा नीचे एक टिप्पणी में बताया गया है, नीचे दी गई विधि मूल प्रश्न के लिए पर्याप्त उत्तर प्रदान नहीं करती है।

जैसा कि this नोट में बताया गया है, axis3d में बहुत सारे हार्ड-कोड किए गए मान हैं जो इसके व्यवहार को अनुकूलित करना मुश्किल बनाते हैं। इसलिए, मुझे नहीं लगता कि वर्तमान एपीआई में ऐसा करने का एक अच्छा तरीका है। जैसा कि नीचे दिखाया आप zaxis की _PLANES पैरामीटर को संशोधित करके "हैक" कर सकते हैं यह:

tmp_planes = ax.zaxis._PLANES 
ax.zaxis._PLANES = (tmp_planes[2], tmp_planes[3], 
        tmp_planes[0], tmp_planes[1], 
        tmp_planes[4], tmp_planes[5]) 
view_1 = (25, -135) 
view_2 = (25, -45) 
init_view = view_2 
ax.view_init(*init_view) 

अब z- अक्ष हमेशा कोई फर्क नहीं पड़ता कि कैसे आप आंकड़ा बारी बारी से आंकड़ा के बाईं ओर स्थित हो जाएगा (जब तक सकारात्मक-जेड दिशा के रूप में इंगित कर रहा है)। हालांकि एक्स-अक्ष और वाई-अक्ष फ्लिपिंग जारी रहेगी। आप _PLANES के साथ खेल सकते हैं और सभी अक्षों के लिए वांछित व्यवहार प्राप्त करने में सक्षम हो सकते हैं लेकिन यह matplotlib के भविष्य के संस्करणों में तोड़ने की संभावना है।

+0

आपको बहुत अधिक क्रेज़ीवेल्फ धन्यवाद। यह थोड़ा अजीब है, मैं इसे काम करने में सक्षम था, हालांकि, यह उम्मीद के अनुसार व्यवहार नहीं करता है। जब मैं आपके संशोधन के बिना स्क्रिप्ट चलाता हूं, तो ज़ेड-अक्ष बाईं ओर था। जब मैंने आपके संशोधन को लागू किया, तो ज़ेड-अक्ष बाईं ओर रहे। मैंने ax.zaxis._PLANES = (tmp [0], tmp [1], tmp [2], tmp [3], tmp [4], tmp [5]) का क्रम बदल दिया और यह धुरी को दाईं ओर ले गया पक्ष (मैं क्या चाहता था)। ऐसा लगता है कि मैं ax.zaxis._PLANES के समान मानों को रीसेट करता हूं लेकिन यह अलग-अलग परिणाम प्राप्त करता है। वैसे भी, फिर से धन्यवाद, यह * बिल्कुल * जो मैं चाहता था, मैं इसकी सराहना करता हूं। – Blink

+0

वूप्स, मैं गलत था। धुरी को बदलने के लिए मैंने ax.zaxis._PLANES = (tmp [1], tmp [2], tmp [3], tmp [4], tmp [5], tmp [0]) का उपयोग किया। यह काम किया; हालांकि, मुझे अभी एहसास हुआ कि यह विमानों पर क्षैतिज/ऊर्ध्वाधर रेखाओं को भी बदल देता है। आप [यहां] (http://i.imagebanana.com/img/vpcs6af2/Selection_005.png) देख सकते हैं कि बैक अक्ष विमानों में कोई क्षैतिज रेखाएं नहीं हैं लेकिन सामने वाले लोग हैं। क्या कोई वेबसाइट बताती है कि कैसे ._PLANES परिभाषित किया गया है? मैंने इसे समझने के लिए लगभग 50 विभिन्न संयोजनों को डालने का प्रयास किया है, लेकिन मैं परिणाम प्राप्त करने में सक्षम नहीं हूं (दाईं तरफ लंबवत धुरी और पीछे की ओर लाइनें) – Blink

+1

मेरी आखिरी टिप्पणी के बाद।मैंने tmp_planes के लिए [0,1,2,3,4,5] के सभी क्रमपरिवर्तनों के माध्यम से चल रहे एक ब्रूट फोर्स टेस्ट को पूरा किया, कुल 720 अलग-अलग व्यवस्थाएं। ** इनमें से कोई भी ** उचित आंकड़े नहीं हुआ। मुझे लगता है कि मैं सिर्फ समस्या से फंस सकता हूं। – Blink

संबंधित मुद्दे