2014-11-04 41 views
7

Tôi có một danh mục ba cột là data và tôi muốn tạo một ô 3D cộng với phép chiếu của mỗi trục như đường bao dự kiến ​​trong mặt phẳng khác hai cái rìu. Cho đến nay tôi có thể làm cho âm mưu 3D bằng cách sử dụng matplotlib mà vẫn không hiển thị bất cứ điều gì từ các thuộc tính của dữ liệu.vẽ sơ đồ chiếu của ô 3D trong ba mặt phẳng sử dụng đường bao

from mpl_toolkits.mplot3d import axes3d 
import matplotlib.pyplot as plt 
from numpy import * 
data=loadtxt('test.cat') 
X=data[:,0] 
Y=data[:,1] 
Z=data[:,2] 
fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
ax.scatter(X, Y, Z, c='r', marker='.') 
ax.set_xlabel('X') 
ax.set_ylabel('Y') 
ax.set_zlabel('Z') 

plt.show() 

Tôi có thể vẽ sơ đồ chiếu của dữ liệu trong mỗi mặt phẳng với colorbar không?

Trả lời

2

Theo những gì bạn muốn làm, bạn cần sử dụng thông số zdir cho các hàm contourcontourf. Ở đây một ví dụ:

import matplotlib.pyplot as plt 
import numpy as np 
from mpl_toolkits.mplot3d import Axes3D 

fig = plt.figure() 
ax = Axes3D(fig) 
X = np.arange(-4, 4, 0.25) 
Y = np.arange(-4, 4, 0.25) 
X, Y = np.meshgrid(X, Y) 
R = np.sqrt(X ** 2 + Y ** 2) 
Z = np.sin(R) 


ax.contourf(X, Y, Z, zdir='x', offset=-4, cmap=plt.cm.hot) 
ax.contour(X, Y, Z, zdir='x', offset=-4, colors='k') 
ax.contourf(X, Y, Z, zdir='y', offset=4, cmap=plt.cm.hot) 
ax.contour(X, Y, Z, zdir='y', offset=4, colors='k') 
ax.contourf(X, Y, Z, zdir='z', offset=-1, cmap=plt.cm.hot) 
ax.contour(X, Y, Z, zdir='z', offset=-1, colors='k') 

plt.show() 

Với kết quả: enter image description here

2

hmm, quả thật vậy, dữ liệu khó khăn để hiển thị. Có thể tạo ra một số lát dọc theo một trục và tạo ra một số ô 2D nhất định sẽ là tốt nhất. Tuy nhiên, các ô 3D là lạ mắt. Tôi đã chơi một chút với dữ liệu dẫn đến một cốt truyện 3D như bạn đã làm và một âm mưu riêng biệt với các phép chiếu.

  • Màu sắc của các điểm được theo các thiếu trục
  • thêm tính minh bạch để cung cấp cho một ý tưởng về mật độ
  • trục giữ của cả hai lô cùng

enter image description here enter image description here

from mpl_toolkits.mplot3d import axes3d 
import matplotlib.pyplot as plt 
import numpy as np 

data = np.loadtxt('test.cat', skiprows=1) 

X=data[:,0] 
Y=data[:,1] 
Z=data[:,2] 

plt.figure() 
ax1 = plt.subplot(111, projection='3d') 

ax1.scatter(X, Y, Z, c='b', marker='.', alpha=0.2) 
ax1.set_xlabel('X - axis') 
ax1.set_ylabel('Y - axis') 
ax1.set_zlabel('Z - axis') 

plt.figure() 
ax2 = plt.subplot(111, projection='3d') 

plt.hot() 

cx = np.ones_like(X) * ax1.get_xlim3d()[0] 
cy = np.ones_like(X) * ax1.get_ylim3d()[1] 
cz = np.ones_like(Z) * ax1.get_zlim3d()[0] 

ax2.scatter(X, Y, cz, c=Z, marker='.', lw=0, alpha=0.2) 
ax2.scatter(X, cy, Z, c=-Y, marker='.', lw=0, alpha=0.2) 
ax2.scatter(cx, Y, Z, c=X, marker='.', lw=0, alpha=0.2) 
ax2.set_xlim3d(ax1.get_xlim3d()) 
ax2.set_ylim3d(ax1.get_ylim3d()) 
ax2.set_zlim3d(ax1.get_zlim3d()) 
ax2.set_xlabel('X - axis') 
ax2.set_ylabel('Y - axis') 
ax2.set_zlabel('Z - axis') 
+0

Tôi thực sự quan tâm đến việc có một âm mưu đường viền trong mỗi mặt phẳng mô tả phép chiếu của trục thứ ba dưới dạng mã màu. – Dalek

4

Đây là hy vọng tôi sẽ không chụp một con muỗi với [rất xấu xí] pháo, tôi gần đây đã một lớp Binning_Array cho một dự án trường học và tôi nghĩ rằng nó có thể có thể giúp bạn: ThreeBinners

import numpy as np 
import matplotlib.pyplot as plt 
import binning_array as ba 
from mpl_toolkits.mplot3d import axes3d 

data = np.loadtxt('test.cat') 
X = data[:,0] 
Y = data[:,1] 
Z = data[:,2] 

n_points = data.shape[0] 

X_min = np.round(np.min(data[:,0])-0.5) 
X_max = np.round(np.max(data[:,0])+0.5) 
Y_min = np.round(np.min(data[:,1])-0.5) 
Y_max = np.round(np.max(data[:,1])+0.5) 
Z_min = np.round(np.min(data[:,2])-0.5) 
Z_max = np.round(np.max(data[:,2])+0.5) 
n_min_bins = 25 
step = min([(X_max-X_min)/n_min_bins, (Y_max-Y_min)/n_min_bins, (Z_max-Z_min)/n_min_bins]) 

# Using three Binners 
BinnerXY = ba.Binning_Array([[X_min, X_max, step], 
          [Y_min, Y_max, step]]) 
BinnerYZ = ba.Binning_Array([[Y_min, Y_max, step], 
          [Z_min, Z_max, step]]) 
BinnerXZ = ba.Binning_Array([[X_min, X_max, step], 
          [Z_min, Z_max, step]]) 

for point in data: 
    BinnerXY.add_value([point[0], point[1]]) 
    BinnerXZ.add_value([point[0], point[2]]) 
    BinnerYZ.add_value([point[1], point[2]]) 

fig = plt.figure() 
ax = [fig.add_subplot(221, projection='3d'), 
     fig.add_subplot(222), 
     fig.add_subplot(223), 
     fig.add_subplot(224)] 

# Plot 2D projections on the 3D graph 
vmin = np.min([BinnerXZ.bin_min(), BinnerYZ.bin_min(), BinnerXY.bin_min()]) 
vmax = np.max([BinnerXZ.bin_max(), BinnerYZ.bin_max(), BinnerXY.bin_max()]) 
levels = np.linspace(vmin,vmax,20) 

xs_c = np.arange(*BinnerXZ.limits[0]) 
zs_c = np.arange(*BinnerXZ.limits[1]) 
ZS_C, XS_C = np.meshgrid(zs_c,xs_c) 
ax[0].contourf(X=XS_C, Y=BinnerXZ.bins, Z=ZS_C, 
       zdir='y', offset=Y_max, 
       vmin=vmin, vmax=vmax, 
       cmap=plt.cm.coolwarm, levels=levels, 
       alpha=0.5) 
xs_c = np.arange(*BinnerXY.limits[0]) 
ys_c = np.arange(*BinnerXY.limits[1]) 
YS_C, XS_C = np.meshgrid(ys_c,xs_c) 
ax[0].contourf(X=XS_C, Y=YS_C, Z=BinnerXY.bins, 
       zdir='z', offset=Z_min, 
       vmin=vmin, vmax=vmax, 
       cmap=plt.cm.coolwarm, levels=levels, 
       alpha=0.5) 
ys_c = np.arange(*BinnerYZ.limits[0]) 
zs_c = np.arange(*BinnerYZ.limits[1]) 
ZS_C, YS_C = np.meshgrid(zs_c, ys_c) 
ax[0].contourf(X=BinnerYZ.bins, Y=YS_C, Z=ZS_C, 
       zdir='x', offset=X_min, 
       vmin=vmin, vmax=vmax, 
       cmap=plt.cm.coolwarm, levels=levels, 
       alpha=0.5) 

# Plot scatter of all data 
ax[0].scatter(X, Y, Z, c='g', marker='.', alpha=0.2) 
ax[0].set_xlabel(r"$x$") 
ax[0].set_ylabel(r"$y$") 
ax[0].set_zlabel(r"$z$") 
max_range = max([X_max-X_min, Y_max-Y_min, Z_max-Z_min])/2. 
pos = [(X_max+X_min)/2., (Y_max+Y_min)/2., (Z_max+Z_min)/2.] 
ax[0].set_xlim(pos[0] - max_range, pos[0] + max_range) 
ax[0].set_ylim(pos[1] - max_range, pos[1] + max_range) 
ax[0].set_zlim(pos[2] - max_range, pos[2] + max_range) 

# Plot 2D histograms 
BinnerXZ.plot_2d_slice(fig=fig, ax=ax[1], xlabel=r"$x$", ylabel=r'$z$') 
BinnerXY.plot_2d_slice(fig=fig, ax=ax[2], xlabel=r"$x$", ylabel=r'$y$') 
BinnerYZ.plot_2d_slice(fig=fig, ax=ax[3], xlabel=r"$y$", ylabel=r'$z$') 
plt.show() 

Bạn có thể cũng chỉ sử dụng một Binner, nhưng lưu ý rằng bạn sẽ nhận được vật nơi các mặt phẳng giao nhau: One Binner

# ... 
# Using three Binners 
# ... 
# Using only one Binner (adds a small error! see comments!) 
Binner = ba.Binning_Array([[X_min, X_max, step], 
          [Y_min, Y_max, step], 
          [Z_min, Z_max, step]]) 
for point in data: 
    Binner.add_value([point[0], point[1], Z_min]) 
    Binner.add_value([point[0], Y_max-step, point[2]]) 
    Binner.add_value([X_min, point[1], point[2]]) 
fig = plt.figure() 
ax = [fig.add_subplot(221, projection='3d'), 
     fig.add_subplot(222), 
     fig.add_subplot(223), 
     fig.add_subplot(224)] 
ax[0].scatter(X, Y, Z, c='g', marker='.', alpha=0.2) 
Binner.plot_slices(others={0:X_min, 1:Y_max, 2:Z_min}, fig=fig, ax=ax) 
plt.show() 

các binning_array.py đã được thực hiện cho một dự án trường học và không hoàn toàn đánh bóng, nhưng nó đủ cho những gì bạn muốn .

import numpy as np 
import matplotlib.pyplot as plt 
from mpl_toolkits.mplot3d import axes3d 

class Binning_Array: 
    def __init__(self, limits=[[-1.,1.,1.],[-1.,1.,1.]]): 
     """Create a new binning array. 
     The amount of given limits determines the dimension of the array, 
     although only 2 and 3D have been tested. 
     Each limit must be a list of start, stop and step for the 
     axis it represents (x, y or z).""" 
     self.limits = np.array(limits) 
     self._shape = [] 
     for i in xrange(len(self.limits)): 
      self._shape.append((self.limits[i][1]-self.limits[i][0])/\ 
           float(self.limits[i][2])) 
     self._shape = tuple(self._shape) 
     self.dimensions = len(self._shape) 
     self.bins = np.zeros(self._shape) 
     self.outside = 0. 
     self._normalized = 1. 

    def __repr__(self): 
     """Representation method. <<REVIEW>>""" 
     return "Binning Array! Hurray!" 

    def __getitem__(self, index): 
     """Direct acess to read self.bins (use something like self[index]) 
     Direct acess to write would be given by __setitem__ 
     """ 
     return self.bins.__getitem__(index) 

    def position2index(self,position,axis=0): 
     """Convert a given position to an index in axis. 
     If it is outside, it returns -1. 
     """ 
     if self.limits[axis][0] <= position < self.limits[axis][1]: 
      return int((position - self.limits[axis][0])/self.limits[axis][2]) 
     else: return -1 

    def index2position(self, index, axis=0): 
     """Convert a given index to a position in axis. 
     If it is outisde, it returns -1. 
     """ 
     if 0 <= index < self._shape[axis]: 
      return self.limits[axis][0] + self.limits[axis][2] * index 
     else: 
      return -1 

    def add_value(self, position, value=1., verbose=False): 
     """Add a given value to a specified position. 
     If verbose it returns a list with the axies at which the position 
     is outside the scope of this Binning_Array. 
     Not very efficient because of that (verbose was for debugging). 
     """ 
     indexs = [] 
     outside = False 
     if verbose: 
      outs = [] 
     for i in xrange(self.dimensions): 
      # using self.dimensions serves as a filter 
      # if position has non valid shape 
      index = self.position2index(position[i],i) 
      if index == -1: 
       if verbose: 
        outside = True 
        outs.append(i) 
       else: 
        self.outside += value/self._normalized 
        return None # nothing, as it is not verbose 
      else: 
       indexs.append(index) 
     if outside: # the only way to get here is if verbose is True... 
      self.outside += value/self._normalized 
      return outs # so I can just return outs... 
     else: 
      self.bins[tuple(indexs)] += value/self._normalized 
      if verbose: 
       return outs 

    def get_value(self, position, verbose=False): 
     """Return the value at the specified position. 
     If verbose it alse returns a list with the axies at which the position 
     is outside the scope of this Binning_Array. 
     """ 
     indexs = [] 
     outside = False 
     if verbose: 
      outs = [] 
     for i in xrange(self.dimensions): 
      index = self.position2index(position[i],i) 
      if index == -1: 
       if verbose: 
        outside = True 
        outs.append[i] 
       else: 
        return self.outside 
      else: 
       indexs.append(index) 
     if outside: # the only way to get here is if verbose is True 
      return self.outside, outs # so I can just return outs... 
     else: 
      if verbose: 
       return self.bins[tuple(indexs)], outs 
      else: 
       return self.bins[tuple(indexs)] 

    def normalize(self, total=None): 
     """Divide the entire array by the sum of its values (and outside). 
     Any value added after this will be normalized by the same factor. 
     """ 
     if total is None: 
      total = self.n_counts() 
     self.bins /= total 
     self.outside /= total 
     self.normalize *= total 

    def n_counts(self): 
     """Return the number of counts.""" 
     return np.sum(self.bins) + self.outside 

    def bin_max(self): 
     """Return the value of the largest bin.""" 
     return np.max(self.bins) 

    def bin_min(self): 
     """Return the value of the largest bin.""" 
     return np.min(self.bins) 

    def plot_2d_slice(self, cuts=[0,1], others={}, 
         fig=None, ax=None, show=True, **kwargs): 
     """Plot a 2D slice.""" 
     x = min(cuts) 
     y = max(cuts) 
     xs = np.arange(self.limits[x][0], 
         self.limits[x][1] + self.limits[x][2], 
         self.limits[x][2]) 
     ys = np.arange(self.limits[y][0], 
         self.limits[y][1] + self.limits[y][2], 
         self.limits[y][2]) 
     index = [] 
     title = '' 
     for i in xrange(self.dimensions): 
      if i in cuts: 
       appendix = slice(self._shape[i]+1) 
      else: 
       appendix = others.get(i,(self.limits[i][0]+ 
             self.limits[i][1])/2.) 
       title += '%d:%.4e\t' % (i,appendix) 
       appendix = self.position2index(appendix,i) 
      index.append(appendix) 
     index = tuple(index) 
     if fig is None: 
      fig, ax = plt.subplots(1,1) 
     YS,XS = np.meshgrid(ys, xs) 
     graph = ax.pcolormesh (XS, YS, self.bins[index], cmap=plt.cm.coolwarm) 
     fig.colorbar(graph, ax=ax) 
     ax.axis('equal') 
     ax.set_xlim(self.limits[x][0], self.limits[x][1]) 
     ax.set_ylim(self.limits[y][0], self.limits[y][1]) 
     if 'xticks' in kwargs: 
      ax.set_xticks(kwargs['xticks']) 
     if 'yticks' in kwargs.keys(): 
      ax.set_yticks(kwargs['yticks']) 
     if 'xlabel' in kwargs: 
      ax.set_xlabel(kwargs['xlabel']) 
     if 'ylabel' in kwargs: 
      ax.set_ylabel(kwargs['ylabel']) 
     if 'xlim' in kwargs: 
      ax.set_xlim(*kwargs['xlim']) 
     if 'ylim' in kwargs: 
      ax.set_ylim(*kwargs['ylim']) 
     if show: 
      fig.tight_layout() 
      fig.show() 

    def plot_slices(self, others={}, fig=None, ax=None, 
        show=True, projections=True): 
     index = [] 
     pos = [] 
     title = '' 
     for i in xrange(self.dimensions): 
      temp = others.get(i,(self.limits[i][0]+self.limits[i][1])/2.) 
      title += '%d:%.4e\t' % (i,temp) 
      pos.append(temp) 
      index.append(self.position2index(temp,i)) 
     if self.dimensions == 3: 
      if fig is None: 
       fig = plt.figure() 
       if projections: 
        ax = [fig.add_subplot(221, projection='3d'), 
          fig.add_subplot(222), 
          fig.add_subplot(223), 
          fig.add_subplot(224)] 
       else: 
        ax = fig.add_subplot(111, projection='3d') 
      if projections: 
       xs = np.arange(self.limits[0][0], 
           self.limits[0][1] + self.limits[0][2], 
           self.limits[0][2]) 
       ys = np.arange(self.limits[1][0], 
           self.limits[1][1] + self.limits[1][2], 
           self.limits[1][2]) 
       zs = np.arange(self.limits[2][0], 
           self.limits[2][1] + self.limits[2][2], 
           self.limits[2][2]) 
       xs_c = np.arange(*self.limits[0]) 
       ys_c = np.arange(*self.limits[1]) 
       zs_c = np.arange(*self.limits[2]) 
       vmin = np.min(self.bins) 
       vmax = np.max(self.bins) 
       levels = np.linspace(vmin,vmax,20) 
       #graph 0 (3D) 
       ax[0].set_xlabel(r"$x$") 
       ax[0].set_ylabel(r"$y$") 
       ax[0].set_zlabel(r"$z$") 
       #ax[0].axis('equal') #not supported in 3D: 
#http://stackoverflow.com/questions/13685386/\ 
#matplotlib-equal-unit-length-with-equal-aspect-ratio-z-axis-is-not-equal-to 
       max_range = max([xs[-1]-xs[0],ys[-1]-ys[0],zs[-1]-zs[0]])/2. 
#    x_mean = (xs[-1] + xs[0])/2. 
#    y_mean = (ys[-1] + ys[0])/2. 
#    z_mean = (zs[-1] +zs[0])/2. 
       ax[0].set_xlim(pos[0] - max_range, pos[0] + max_range) 
       ax[0].set_ylim(pos[1] - max_range, pos[1] + max_range) 
       ax[0].set_zlim(pos[2] - max_range, pos[2] + max_range) 
       # to understand holes in contour plot: 
#http://stackoverflow.com/questions/18897950/\ 
#matplotlib-pyplot-contourf-function-introduces-holes-or-gaps-when-plotting-regul 
       # graph 1 (2D) 
       ZS, XS = np.meshgrid(zs,xs) 
       ZS_C, XS_C = np.meshgrid(zs_c,xs_c) 
       ax[1].pcolormesh(XS, ZS, self.bins[:,index[1],:], 
          vmin=vmin, vmax=vmax, 
          cmap=plt.cm.coolwarm) 
       ax[0].contourf(X=XS_C, Y=self.bins[:,index[1],:], Z=ZS_C, 
           zdir='y', offset=pos[1], 
           vmin=vmin, vmax=vmax, 
           cmap=plt.cm.coolwarm, levels=levels, 
           alpha=0.5) 
       ax[1].set_xlabel(r"$x$") 
       ax[1].set_ylabel(r"$z$") 
       ax[1].set_xlim(xs[0],xs[-1]) 
       ax[1].set_ylim(zs[0],zs[-1]) 
       ax[1].axis('equal') 
       # graph 2 (2D) 
       YS, XS = np.meshgrid(ys,xs) 
       YS_C, XS_C = np.meshgrid(ys_c,xs_c) 
       ax[2].pcolormesh(XS, YS, self.bins[:,:,index[2]], 
           vmin=vmin, vmax=vmax, 
           cmap=plt.cm.coolwarm) 
       ax[0].contourf(X=XS_C, Y=YS_C, Z=self.bins[:,:,index[2]], 
           zdir='z', offset=pos[2], 
           vmin=vmin, vmax=vmax, 
           cmap=plt.cm.coolwarm, levels=levels, 
           alpha=0.5) 
       ax[2].set_xlabel(r"$x$") 
       ax[2].set_ylabel(r"$y$") 
       ax[2].set_xlim(xs[0],xs[-1]) 
       ax[2].set_ylim(ys[0],ys[-1]) 
       ax[2].axis('equal') 
       # graph 3 (2D) 
       ZS, YS = np.meshgrid(zs, ys) 
       ZS_C, YS_C = np.meshgrid(zs_c, ys_c) 
       ax[3].pcolormesh(YS, ZS, self.bins[index[0],:,:], 
           vmin=vmin, vmax=vmax, 
           cmap=plt.cm.coolwarm) 
       ax[0].contourf(X=self.bins[index[0],:,:], Y=YS_C, Z=ZS_C, 
           zdir='x', offset=pos[0], 
           vmin=vmin, vmax=vmax, 
           cmap=plt.cm.coolwarm, levels=levels, 
           alpha=0.5) 
       ax[3].set_xlabel(r"$y$") 
       ax[3].set_ylabel(r"$z$") 
       ax[3].set_xlim(ys[0],ys[-1]) 
       ax[3].set_ylim(zs[0],zs[-1]) 
       ax[3].axis('equal') 
      else: 
       # update to draw a given slice, use it to plot eaxh axes above! 
       ax.plot(self.XS,self.YS,self.ZS) 
       ax.set_zlabel(r"$z$") 
       ax.set_xlabel(r"$x$") 
       ax.set_ylabel(r"$y$") 
       ax.axis('equal') 
     else: 
      if fig is None: 
       fig, ax = plt.subplots(1) 
      xs = np.arange(self.limits[0][0], 
          self.limits[0][1] + self.limits[0][2], 
          self.limits[0][2]) 
      ys = np.arange(self.limits[1][0], 
          self.limits[1][1] + self.limits[1][2], 
          self.limits[1][2],) 
      YS, XS = np.meshgrid(ys, xs) 
      graph = ax.pcolormesh(XS, YS, self.bins, cmap=plt.cm.coolwarm) 
      fig.colorbar(graph) 
      ax.set_xlim(self.limits[0][0], self.limits[0][1]) 
      ax.set_ylim(self.limits[1][0], self.limits[1][1]) 
      ax.set_title('Energy Distribution') 
      ax.set_xlabel(r"$x$") 
      ax.set_ylabel(r"$y$") 
      ax.axis('equal') 
     if show: 
      fig.tight_layout() 
      fig.show() 
     return fig, ax 

Nếu bất kỳ điều gì trên mã sai hoặc bị lỗi, vui lòng nói như vậy và tôi sẽ chỉnh sửa ở trên (dự án trường đã được chấm điểm, vì vậy bạn sẽ không làm bài tập ở nhà).
Ngoài ra, nếu có điều gì không rõ ràng, vui lòng nói để tôi thêm nhận xét hoặc giải thích khi cần.

+0

Cốt truyện được chiếu là rất ấn tượng! – Dalek

Các vấn đề liên quan