0

So i am working in a crystallographic project and I'm in front of a problem. What i'm trying to do in this code is to plot the reciprocal space of my cristal. More importantly some specific planes of my crystal.

I suppose that there are not a lot of chemists and physicists in this forum so I'm going to try to explain my problem without the background. I have a code that build a 3D plot of my "atoms" (points) in my cristal. Each atom has an index H,K and L in a 3D matrix and for each set of 3 indexes you have a space coordinate (x,y,z). Exemple of full 3d plot : 1 But what I really want is a 2D plot of a set of planes in this space exemple of a plane with the normal 1-11 : 2 for a final representation looking like that : 3

So here is my code :

from numpy import *
from math import *
from cmath import *
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.pyplot import *

print('###########################################')
print('Bienvenue sur CR7-Cristallix the 7th wonder')
print('###########################################')

#ensemble des variables
###################################################################################
dir=array([0,0,0])
ar,br,cr=0,0,0 #vecteur réseau réciproque
cif=array([0.,0.,0.])
f=array([1,0,0]) # vecteurs unitaire du réseau direct f,g,h
g=array([0,1,0])
h=array([0,0,1])
n=4 # taille du tenseur
motif=array([0,0,0]) # motif du cristal, prévu pour plus tard si amélioration avec un fichier cif
fd=1. # facteur de diffusion atomique non utilisé pour le moment
v=array([0,0,0])#sert à comparer grace au produit scalaire entre la direction choisie et l'ensemble des vecteurs
y,t=0,0
fig = plt.figure()#utilisés pour définir ax.scatter
ax = fig.add_subplot(111, projection='3d')
###################################################################################

#ensemble des inputs
###################################################################################
for i in range (len(dir)):
    dir[i]=int(input('just enter 0 0 1 one by one (it's the normal to the plane:'))
res, a, b, c=input('type of lattice (type F) : '),float(input('a : ')),float(input('b : ')),float(input('c : '))#entre les paramètres de maille et le réseau
n=int(input('dimension of reciprocal space (go for 2or3or4 : '))#entre la taille du tenseur, de hkl max et min. (-n,n)=(h/k/lmin,h/k/lmax)
###################################################################################



#fonction pour créer les vecteurs du réseau réciproque
###################################################################################
def rep():
    global a,b,c,ar,br,cr
    #vecteurs de maille pour chaque réseau
    if res=='P':
        a,b,c=a*f,b*g,c*h
    elif res =='F':
        a,b,c=(b/2)*g+(c/2)*h,(a/2)*f+(c/2)*h,(a/2)*f+(b/2)*g
    elif res =='I':
        a,b,c=-a/2*f+b/2*g+c/2*h,a/2*f-b/2*g+c/2*h,a/2*f+b/2*g-c/2*h  
    #calcul du volume de la maille
    V=vdot(a,cross(b,c))
    #calcul des vecteurs du réseau réciproque
    ar,br,cr=2*pi*(1/V)*cross(b,c),2*pi*(1/V)*cross(c,a),2*pi*(1/V)*cross(a,b)
    return(a,b,c,ar,br,cr)

rep()
###################################################################################

#fonction qui calcule le facteur de structure et les extinctions
###################################################################################
def facteur(res,cif):#rajouter de nouveaux paramètres à terme
    global ext
    ext=zeros((2*n+1,2*n+1,2*n+1))
    #calcul des raies d'extinction pour chaque réseau avec le facteur de structure
    if res=='P':
        for i in range (-n,n+1):
            for j in range (-n,n+1):
                for k in range (-n,n+1):
                        ext[i][j][k]=real(fd*exp(2j*pi*(i*cif[0]+j*cif[1]+k*cif[2])))
    elif res =='F':
        for i in range (-n,n+1):
            for j in range (-n,n+1):
                for k in range (-n,n+1):
                        ext[i][j][k]=real(fd*exp(2j*pi*(i*cif[0]+j*cif[1]+k*cif[2]))*(1+exp(1j*pi*(i+j))+exp(1j*pi*(i+k))+exp(1j*pi*(k+j))))/4
    elif res =='I':
        for i in range (-n,n+1):
            for j in range (-n,n+1):
                for k in range (-n,n+1):
                        ext[i][j][k]=real(fd*exp(2j*pi*(i*cif[0]+j*cif[1]+k*cif[2]))*(1+exp(1j*pi*(i+j+k))))/2
    else:
        print('Choisissez entre ces réseaux P, F ou I (mon programmeur est encore trop limité)')
#renvoie un tenseur d'ordre 3 avec pour des indices i,j,k correspondant à h,k,l, une valeur 1 ou 0 selon raie ou extinction   
facteur(res,cif)
################################################################################### 

#création du réseau réciproque et affichage de celui-ci en fonction du plan indiqué
###################################################################################
coord=zeros((2*n+1,2*n+1,2*n+1,3))
for i in range (-n,n+1):
    for j in range (-n,n+1):
        for k in range (-n,n+1):
            coord[i][j][k]=ext[i][j][k]*(ar+br+cr)*array([i,j,k])
print(coord) # bugtest
###################################################################################

###################################################################################
for i in range (-n,n+1):
    for j in range (-n,n+1):
        for k in range (-n,n+1):
            v=vdot(coord[i][j][k],dir)
            if v==0:#on ne conserve que les vecteurs appartenant au plan de la normal dir
                #figure()
                s=str((i,j,k))
                ax.scatter(coord[i][j][k][0],coord[i][j][k][1],coord[i][j][k][2]) #plot du réseau, manque l'automatisation du
                ax.text(coord[i][j][k][0],coord[i][j][k][1],coord[i][j][k][2],s,size=7)
z=array([0,0,1])
e=array([0,1,0])
w=[float(dir[0]),float(dir[1]),float(dir[2])]
calphi=vdot(z,w)/(linalg.norm(z)*linalg.norm(w))
calthe=vdot(z,w)/(linalg.norm(z)*linalg.norm(w))
angphi=real(acos(calphi)*180/pi) 
angthe=real(acos(calthe)*180/pi)
# ax.view_init(90,0)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')

In the last part i tried to see if i could play with viewing angles of the 3D plot in order to plot my plane and maybe after that make disappear the axis. But you can't rotate the 3d plot as you want. Sorry I know that it is not well explained and the code is very long but I will be happy if someone can help me. Thank you very much.

edit1: here the code for a minimal exemple. For the inputs you have a,b and c which are the lattice parameters of my cristal (for exemple a=5 b=5 and c=5 for a cube) and h, k and l which are the coordinate of the vector normal to the plane you want (if you put 0 0 0 you'll have the full cristal, try to put 1 0 0 for a simple plane and 1 1 0 for one i don't know how to plot in 2d). Try to change n=1 or 2 (at the beginning of the code) to have a better visibility .

from numpy import *
from math import *
from cmath import *
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.pyplot import *

print('###########################################')
print('Bienvenue sur CR7-Cristallix the 7th wonder')
print('###########################################')

#########################parameters######################################
dir=array([0,0,0])
n=4 #dimension of cristal
v=array([0,0,0])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
coord=zeros((2*n+1,2*n+1,2*n+1,3))

##########################inputs#########################################
a, b, c=float(input('a : ')),float(input('b : ')),float(input('c : '))

for i in range (len(dir)):
    dir[i]=int(input('enter the indexis of the normal to the plane you want one by one: '))
###########################create the cells of my cristal################
ext=ones((2*n+1,2*n+1,2*n+1))
for i in range (-n,n+1):
    for j in range (-n,n+1):
        for k in range (-n,n+1):
                coord[i][j][k]=ext[i][j][k]*(a+b+c)*array([i,j,k])
############################create the plane perpendicular to the direction i put (dir)####################################
for i in range (-n,n+1):
    for j in range (-n,n+1):
        for k in range (-n,n+1):
            v=vdot(coord[i][j][k],dir)
            if v==0:
                s=str((i,j,k))
                ax.scatter(coord[i][j][k][0],coord[i][j][k][1],coord[i][j][k][2])
                ax.text(coord[i][j][k][0],coord[i][j][k][1],coord[i][j][k][2],s,size=7)
###################################################################################

edit2: I think i find the answer, look for the algorithm of Gram-Schmidt.

Rubueno
  • 1
  • 1
  • Can you please specify your ultimate goal? Do you want to have all atoms of one lattice plane plotted in a 2D system that is inside this plane? Do you want to slice along one plane or project several? What about the reference frame? Do you have atomic coordinates in relative lattice units or in cartesian coordinates? The code is really TO LONG! For example, Why is the calculation of the structure factor important? – dnalow Aug 06 '20 at 16:51
  • my ultimate goal is to slice along one plane and to plot it in 2D (just this plane). All my atoms are in relative lattice units. The structure factor is important for the final goal of my project, that is plotting the reciprocal space of my cristal. But my to resume my main problem is : how to plot in 2D the slice containing atoms of a 3D cristal. I have to keep the symetries. – Rubueno Aug 06 '20 at 17:08
  • A minimal example of your problem would make it much easier to help though – dnalow Aug 06 '20 at 17:52
  • Thank you for your time, i edited my message with the new code for a minimal example. – Rubueno Aug 06 '20 at 18:24

0 Answers0