0

I have a matrix generated by parsing a file the numpy array is the size 101X101X41 and each entry has a value which represents the magnitude at each point.

Now what I want to do is to plot it in a 3d plot where the 4th dimension will be represented by color. so that I will be able to see the shape of the data points (represent molecular orbitals) and deduce its magnitude at that point.

If I plot each slice of data I get the desired outcome, but in a 2d with the 3rd dimension as the color.

Is there a way to plot this model in python using Matplotlib or equivalent library

Thanks

EDIT:

Im trying to get the question clearer to what I desire.

Ive tried the solution suggested but ive received the following plot:

enter image description here

as one can see, due to the fact the the mesh has lots of zeros in it it "hide" the 3d orbitals. in the following plot one can see a slice of the data, where I get the following plot:

enter image description here

So as you can see I have a certain structure I desire to show in the plot.

my question is, is there a way to plot only the structure and ignore the zeroes such that they won't "hide" the structure.

the code I used to generate the plots:

x = np.linspase(1,101,101)
y = np.linspase(1,101,101)
z = np.linspase(1,101,101)

xx,yy,zz = np.meshgrid(x,y,z)
fig=plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xx, yy, zz, c=cube.calc_data.flatten())
plt.show()

plt.imshow(cube.calc_data[:,:,11],cmap='jet')
plt.show()

Hope that now the question is much clearer, and that you'd appreciate the question enough now to upvote

Thanks.

Community
  • 1
  • 1
  • 3
    Possible duplicate of [How to make a 4d plot with matplotlib using arbitrary data](https://stackoverflow.com/questions/14995610/how-to-make-a-4d-plot-with-matplotlib-using-arbitrary-data) – f.wue May 03 '19 at 09:00
  • You forgot the `meshgrid` part of the solution. – ImportanceOfBeingErnest May 03 '19 at 10:53
  • @ImportanceOfBeingErnest Ive added the mesh grid and got x,y,z each in the size 101X101X41 but then when I give my data matrix to scatter I get the following error - ValueError: 'c' argument has 101 elements, which is not acceptable for use with 'x' with size 418241, 'y' with size 418241. –  May 03 '19 at 11:15
  • Guys don't forget this is a platform that meant to help others also, how one should learn how to improve his skill in this platform if people which have much more experience down vote him instead to guide him, think about it. this question show that he tried and followed this platform rules to ask and improve his question – David May 03 '19 at 11:23
  • You do not show `data` in the code, but I suspect it needs to be `c=data.flatten()`. – ImportanceOfBeingErnest May 03 '19 at 11:49

2 Answers2

0

you can perform the following:

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
epsilon = 2.5e-2 # threshold
height, width, depth = data.shape

global_min = np.inf
global_max = -np.inf

for d in range(depth):
    slice = data[:, :, d]
    minima = slice.min()
    if (minima < global_min): global_min = minima
    maxima = slice.max()
    if (maxima>global_max): global_max=maxima
    norm = colors.Normalize(vmin=minima, vmax=maxima, clip=True)
    mapper = cm.ScalarMappable(norm=norm, cmap=cm.jet)
    points_gt_epsilon = np.where(slice >= epsilon)
    ax.scatter(points_gt_epsilon[0], points_gt_epsilon[1], d,
                   c=mapper.to_rgba(data[points_gt_epsilon[0],points_gt_epsilon[1],d]), alpha=0.015, cmap=cm.jet)
    points_lt_epsilon = np.where(slice <= -epsilon)
    ax.scatter(points_lt_epsilon[0], points_lt_epsilon[1], d,
                   c=mapper.to_rgba(data[points_lt_epsilon[0], points_lt_epsilon[1], d]), alpha=0.015, cmap=cm.jet)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.title('Electron Density Prob.')
norm = colors.Normalize(vmin=global_min, vmax=global_max, clip=True)
cax, _ = colorbar.make_axes(ax)
colorbar.ColorbarBase(cax, cmap=cm.jet,norm=norm)
plt.savefig('test.png')
plt.clf()

What this piece of code does is going slice by slice from the data matrix and for each scatter plot only the points desired (depend on epsilon).

in this case you avoid plotting a lot of zeros that 'hide' your model, using your words.

Hope this helps

David
  • 8,113
  • 2
  • 17
  • 36
0

You can adjust the color and size of the markers for the scatter. So for example you can filter out all markers below a certain threshold by putting their size to 0. You can also make the size of the marker adaptive to the field strength.

As an example:

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

f = lambda x,y,z: np.exp(-(x-3)**2-(y-3)**2-(z-1)**2) - \
                  np.exp(-(x+3)**2-(y+3)**2-(z+1)**2)
t1 = np.linspace(-6,6,101)
t2 = np.linspace(-3,3,41)

# Data of shape 101,101,41
data = f(*np.meshgrid(t1,t1,t2))
print(data.shape)

# Coordinates
x = np.linspace(1,101,101)
y = np.linspace(1,101,101)
z = np.linspace(1,101,41)
xx,yy,zz = np.meshgrid(x,y,z)


fig=plt.figure()
ax = fig.add_subplot(111, projection='3d')

s = np.abs(data/data.max())**2*25
s[np.abs(data) < 0.05] = 0
ax.scatter(xx, yy, zz, s=s, c=data.flatten(), linewidth=0, cmap="jet", alpha=.5)
plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Sorry to not give an upvote to the question. The reason is that it does not contain a runnable example to start with, forcing me to create such data myself. I generally do not upvote such questions. – ImportanceOfBeingErnest May 08 '19 at 10:59