├── README.md ├── combine_basis_cell.py ├── get_basis_image.py ├── get_batch_images.py ├── get_cell_image.py ├── iMatGen-VO_dataset_generated_strctures.tar ├── iMatGen.tar ├── img2basis.py └── img2cell.py /README.md: -------------------------------------------------------------------------------- 1 | # imatgen 2 | image-based generative model for inverse design of solid state materials (currently running on python2) \ 3 | -------------------------------------------------------------------------------- /combine_basis_cell.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import glob 3 | 4 | from tqdm import tqdm 5 | 6 | from ase.io import read,write 7 | 8 | for name in glob.glob('./../cell/*.cif'): 9 | cif_name = name.split('/')[-1] 10 | print cif_name 11 | cell = read(name) 12 | cg_cell = cell.get_positions() 13 | 14 | real_mat = read('./../basis/'+cif_name) 15 | pos = real_mat.get_positions() 16 | 17 | delta = cg_cell - np.mean(pos,0) 18 | new_pos = pos+delta 19 | 20 | real_mat.set_cell(cell.get_cell()) 21 | real_mat.set_positions(new_pos) 22 | 23 | write('./'+cif_name[:-4]+'.vasp',real_mat) 24 | -------------------------------------------------------------------------------- /get_basis_image.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import math 3 | import os 4 | import random 5 | import json 6 | from ase.io import read,write 7 | from ase import Atom, Atoms 8 | import argparse 9 | import numpy 10 | import numpy as np 11 | from numpy.linalg import norm 12 | from tqdm import tqdm 13 | from joblib import Parallel, delayed 14 | import multiprocessing 15 | import pickle 16 | 17 | def get_atomlist_atomindex(): 18 | # cod_atomlist = ['Ru', 'Re', 'Ra', 'Rb', 'Rn', 'Rh', 'Be', 'Ba', 'Bi', 'Bk', 'Br', 'H', 'P', 'Os', 'Ge', 'Gd', 'Ga', 'Pr', 'Pt', 'Pu', 'C', 'Pb', 'Pa', 'Pd', 'Cd', 'Po', 'Pm', 'Ho', 'Hf', 'Hg', 'He', 'Mg', 'K', 'Mn', 'O', 'S', 'W', 'Zn', 'Eu', 'Zr', 'Er', 'Ni', 'Na', 'Nb', 'Nd', 'Ne', 'Np', 'Fe', 'B', 'F', 'Sr', 'N', 'Kr', 'Si', 'Sn', 'Sm', 'V', 'Sc', 'Sb', 'Se', 'Co', 'Cm', 'Cl', 'Ca', 'Cf', 'Ce', 'Xe', 'Tm', 'Cs', 'Cr', 'Cu', 'La', 'Li', 'Tl', 'Lu', 'Th', 'Ti', 'Te', 'Tb', 'Tc', 'Ta', 'Yb', 'Dy', 'I', 'U', 'Y', 'Ac', 'Ag', 'Ir', 'Am', 'Al', 'As', 'Ar', 'Au', 'In', 'Mo'] # 96 19 | 20 | # mp_atomlist = ['Ru', 'Re', 'Rb', 'Rh', 'Be', 'Ba', 'Bi', 'Br', 'H', 'P', 'Os', 'Ge', 'Gd', 'Ga', 'Pr', 'Pt', 'Pu', 'Mg', 'Pb','Pa', 'Pd', 'Cd', 'Pm', 'Ho', 'Hf', 'Hg', 'He', 'C', 'K', 'Mn', 'O', 'S', 'W', 'Zn', 'Eu', 'Zr', 'Er', 'Ni', 'Na','Nb', 'Nd', 'Ne', 'Np', 'Fe', 'B', 'F', 'Sr', 'N', 'Kr', 'Si', 'Sn', 'Sm', 'V', 'Sc', 'Sb', 'Se', 'Co', 'Cl', 'Ca','Ce', 'Xe', 'Tm', 'Cs', 'Cr', 'Cu', 'La', 'Li', 'Tl', 'Lu', 'Th', 'Ti', 'Te', 'Tb', 'Tc', 'Ta', 'Yb', 'Dy', 'I','U', 'Y', 'Ac', 'Ag', 'Ir', 'Al', 'As', 'Ar', 'Au', 'In', 'Mo'] #89 21 | 22 | # all_atomlist = list(set(cod_atomlist+mp_atomlist)) 23 | 24 | # You can specify your own element lists (if you don't want to use the above list) 25 | all_atomlist = ['V','O'] 26 | 27 | 28 | cod_atomindex = {} 29 | for i,symbol in enumerate(all_atomlist): 30 | cod_atomindex[symbol] = i 31 | return cod_atomlist,cod_atomindex 32 | 33 | 34 | def get_scale(sigma): 35 | scale = 1.0/(2*sigma**2) 36 | return scale 37 | 38 | def get_image_one_atom(atom,fakeatoms_grid,nbins,scale): 39 | grid_copy = fakeatoms_grid.copy() 40 | ngrid = len(grid_copy) 41 | image = numpy.zeros((1,nbins**3)) 42 | grid_copy.append(atom) 43 | drijk = grid_copy.get_distances(-1,range(0,nbins**3),mic=True) 44 | pijk = numpy.exp(-scale*drijk**2) 45 | image[:,:] = pijk.flatten() 46 | return image.reshape(nbins,nbins,nbins) 47 | 48 | def get_fakeatoms_grid(atoms,nbins): 49 | atomss = [] 50 | scaled_positions = [] 51 | ijks = [] 52 | grid = numpy.array([float(i)/float(nbins) for i in range(nbins)]) 53 | yv,xv,zv = numpy.meshgrid(grid,grid,grid) 54 | pos = numpy.zeros((nbins**3,3)) 55 | pos[:,0] = xv.flatten() 56 | pos[:,1] = yv.flatten() 57 | pos[:,2] = zv.flatten() 58 | atomss = Atoms('H'+str(nbins**3)) 59 | atomss.set_cell(atoms.get_cell())#making pseudo-crystal containing H positioned at pre-defined fractional coordinate 60 | atomss.set_pbc(True) 61 | atomss.set_scaled_positions(pos) 62 | fakeatoms_grid = atomss 63 | return fakeatoms_grid 64 | 65 | def get_image_all_atoms(atoms,nbins,scale,norm,num_cores): 66 | fakeatoms_grid = get_fakeatoms_grid(atoms,nbins) 67 | cell = atoms.get_cell() 68 | imageall_gen = Parallel(n_jobs=num_cores)(delayed(get_image_one_atom)(atom,fakeatoms_grid,nbins,scale) for atom in atoms) 69 | imageall_list = list(imageall_gen) 70 | cod_atomlist,cod_atomindex = get_atomlist_atomindex() 71 | nchannel = len(cod_atomlist) 72 | channellist = [] 73 | for i,atom in enumerate(atoms): 74 | channel = cod_atomindex[atom.symbol] 75 | channellist.append(channel) 76 | channellist = list(set(channellist)) 77 | nc = len(channellist) 78 | shape = (nbins,nbins,nbins,nc) 79 | image = numpy.zeros(shape) 80 | for i,atom in enumerate(atoms): 81 | nnc = channellist.index(cod_atomindex[atom.symbol]) 82 | img_i = imageall_list[i] 83 | image[:,:,:,nnc] += img_i * (img_i>=0.02) 84 | 85 | return image,channellist 86 | 87 | def image2pickle(image,channellist,savefilename): 88 | dic = {'image':image.tolist(),'channel':channellist.tolist()} 89 | with open(savefilename,'w') as f: 90 | json.dump(dic,f) 91 | 92 | 93 | def basis_translate(atoms): 94 | N = len(atoms) 95 | pos = atoms.positions 96 | cg = np.mean(pos,0) 97 | dr = 7.5 - cg #move to center of 15A-cubic box 98 | dpos = np.repeat(dr.reshape(1,3),N,0) 99 | new_pos = dpos + pos 100 | atoms_ = atoms.copy() 101 | atoms_.cell = 15.0*np.identity(3) 102 | atoms_.positions = new_pos 103 | return atoms_ 104 | 105 | def file2image(args): 106 | inputfiles = args.input_file 107 | random.shuffle(inputfiles) 108 | for inputfile in inputfiles: 109 | tmp = inputfile.split('/')[-1].split('.')[0]; tmp2 = inputfile.split('.')[0] 110 | touchfile = tmp2+'.touchtouch' 111 | filename2 = './'+tmp+'_64.pickle' 112 | savefilename = './'+tmp+'_32.npy'#'.pickle' 113 | if os.path.isfile(filename2) or os.path.isfile(savefilename): 114 | print('already made pickle') 115 | pass 116 | if os.path.isfile(touchfile): 117 | pass 118 | os.system('touch '+touchfile) 119 | try: 120 | atoms = read(inputfile,format = args.filetype) 121 | except: 122 | os.system('rm '+inputfile) 123 | continue 124 | scale = get_scale(sigma=0.26) # values for Gaussain width 125 | num_cores = args.nproc 126 | nbins = args.nbins # the number of grid for generated output image 127 | 128 | image,channellist = get_image_all_atoms(basis_translate(atoms),nbins,scale,norm,num_cores) 129 | image2pickle(image,channellist,savefilename) 130 | os.system('rm '+touchfile) 131 | return 1 132 | 133 | def main(): 134 | parser = argparse.ArgumentParser(description='mapping POSCAR or cif structure into a box image') 135 | parser.add_argument('--input_file', type=str,nargs='+', 136 | help='a file path with the poscar or cif structure') 137 | parser.add_argument('--filetype', type=str,default='cif', 138 | help='filetype : cif,vasp') 139 | parser.add_argument('--nbins', type=int,default=32, 140 | help='number of bins in one dimension') 141 | parser.add_argument('--nproc', type=int,default=1, 142 | help='number of process') 143 | 144 | args = parser.parse_args() 145 | file2image(args) 146 | return 1 147 | 148 | if __name__=='__main__': 149 | main() 150 | 151 | 152 | -------------------------------------------------------------------------------- /get_batch_images.py: -------------------------------------------------------------------------------- 1 | #!/qcfs/jackjack5/3party-software/anaconda/kdft/anaconda2/bin/python 2 | 3 | import glob 4 | import argparse 5 | import os 6 | import numpy as np 7 | import pickle 8 | import sys 9 | from tqdm import tqdm 10 | import random 11 | 12 | def makebatch(args): 13 | filelist = glob.glob(args.files+'/*.json') 14 | batchsize = args.batchsize 15 | savedir = args.savedir 16 | batch_iter = 0 17 | batch_images = [] 18 | batch_channels = [] 19 | random.seed(777) # You can also change random seed value 20 | random.shuffle(filelist) 21 | tt = np.array(filelist) 22 | if not os.path.isdir(savedir): 23 | os.mkdir(savedir) 24 | sum_nc = 0 25 | for filename in tqdm(filelist): 26 | if not '.npy' in filename: 27 | continue 28 | images = np.array(json.load(open(filename))['image']) 29 | dim = images.shape[0] 30 | nc = images.shape[-1] 31 | sum_nc += nc 32 | for c in range(nc): 33 | batch_images.append(images[:,:,:,c].reshape(dim,dim,dim,1)) 34 | if len(batch_images)==batchsize: 35 | print 'saving batch #',batch_iter 36 | print sum_nc 37 | batch_savefilename1 = savedir+'/'+str(batch_iter)+'_images.npy' 38 | batch_savefilename2 = savedir+'/'+str(batch_iter)+'_pvals.npy' 39 | fin_batch = np.array(batch_images) 40 | (p,q,r,s,t) = np.where(fin_batch >= 0.02) 41 | pvals = fin_batch[p,q,r,s,t] 42 | fin_batch2 = np.array([p,q,r,s,t],np.int32) 43 | np.save(batch_savefilename1, fin_batch2) 44 | np.save(batch_savefilename2, np.array(pvals)) 45 | batch_iter += 1 46 | batch_images = [] 47 | batch_channels = [] 48 | return 1 49 | 50 | def main(): 51 | parser = argparse.ArgumentParser(description='script for making single image batches') 52 | parser.add_argument('--savedir',type=str,default='batch_images/', 53 | help = 'save destination for batch images') 54 | parser.add_argument('--files',type=str, 55 | help = 'input image files, xx.npy') 56 | parser.add_argument('--batchsize',type=int,default=20, 57 | help = 'the size of batches') 58 | args = parser.parse_args() 59 | 60 | makebatch(args) 61 | 62 | return 63 | 64 | 65 | 66 | if __name__=='__main__': 67 | main() 68 | 69 | 70 | -------------------------------------------------------------------------------- /get_cell_image.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import math 3 | import os 4 | import random 5 | import json 6 | from ase.io import read,write 7 | from ase import Atom, Atoms 8 | import argparse 9 | import numpy 10 | import numpy as np 11 | from numpy.linalg import norm 12 | from tqdm import tqdm 13 | from joblib import Parallel, delayed 14 | import multiprocessing 15 | import pickle 16 | 17 | def get_atomlist_atomindex(): 18 | # cod_atomlist = ['Ru', 'Re', 'Ra', 'Rb', 'Rn', 'Rh', 'Be', 'Ba', 'Bi', 'Bk', 'Br', 'H', 'P', 'Os', 'Ge', 'Gd', 'Ga', 'Pr', 'Pt', 'Pu', 'C', 'Pb', 'Pa', 'Pd', 'Cd', 'Po', 'Pm', 'Ho', 'Hf', 'Hg', 'He', 'Mg', 'K', 'Mn', 'O', 'S', 'W', 'Zn', 'Eu', 'Zr', 'Er', 'Ni', 'Na', 'Nb', 'Nd', 'Ne', 'Np', 'Fe', 'B', 'F', 'Sr', 'N', 'Kr', 'Si', 'Sn', 'Sm', 'V', 'Sc', 'Sb', 'Se', 'Co', 'Cm', 'Cl', 'Ca', 'Cf', 'Ce', 'Xe', 'Tm', 'Cs', 'Cr', 'Cu', 'La', 'Li', 'Tl', 'Lu', 'Th', 'Ti', 'Te', 'Tb', 'Tc', 'Ta', 'Yb', 'Dy', 'I', 'U', 'Y', 'Ac', 'Ag', 'Ir', 'Am', 'Al', 'As', 'Ar', 'Au', 'In', 'Mo'] # 96 19 | 20 | # mp_atomlist = ['Ru', 'Re', 'Rb', 'Rh', 'Be', 'Ba', 'Bi', 'Br', 'H', 'P', 'Os', 'Ge', 'Gd', 'Ga', 'Pr', 'Pt', 'Pu', 'Mg', 'Pb','Pa', 'Pd', 'Cd', 'Pm', 'Ho', 'Hf', 'Hg', 'He', 'C', 'K', 'Mn', 'O', 'S', 'W', 'Zn', 'Eu', 'Zr', 'Er', 'Ni', 'Na','Nb', 'Nd', 'Ne', 'Np', 'Fe', 'B', 'F', 'Sr', 'N', 'Kr', 'Si', 'Sn', 'Sm', 'V', 'Sc', 'Sb', 'Se', 'Co', 'Cl', 'Ca','Ce', 'Xe', 'Tm', 'Cs', 'Cr', 'Cu', 'La', 'Li', 'Tl', 'Lu', 'Th', 'Ti', 'Te', 'Tb', 'Tc', 'Ta', 'Yb', 'Dy', 'I','U', 'Y', 'Ac', 'Ag', 'Ir', 'Al', 'As', 'Ar', 'Au', 'In', 'Mo'] #89 21 | 22 | # all_atomlist = list(set(cod_atomlist+mp_atomlist)) 23 | 24 | # You can specify your own element lists (if you don't want to use the above list) 25 | all_atomlist = ['V'] 26 | 27 | 28 | cod_atomindex = {} 29 | for i,symbol in enumerate(all_atomlist): 30 | cod_atomindex[symbol] = i 31 | return cod_atomlist,cod_atomindex 32 | 33 | 34 | def get_scale(sigma): 35 | scale = 1.0/(2*sigma**2) 36 | return scale 37 | 38 | def get_image_one_atom(atom,fakeatoms_grid,nbins,scale): 39 | grid_copy = fakeatoms_grid.copy() 40 | ngrid = len(grid_copy) 41 | image = numpy.zeros((1,nbins**3)) 42 | grid_copy.append(atom) 43 | drijk = grid_copy.get_distances(-1,range(0,nbins**3),mic=True) 44 | pijk = numpy.exp(-scale*drijk**2) 45 | image[:,:] = pijk.flatten() 46 | return image.reshape(nbins,nbins,nbins) 47 | 48 | def get_fakeatoms_grid(atoms,nbins): 49 | atomss = [] 50 | scaled_positions = [] 51 | ijks = [] 52 | grid = numpy.array([float(i)/float(nbins) for i in range(nbins)]) 53 | yv,xv,zv = numpy.meshgrid(grid,grid,grid) 54 | pos = numpy.zeros((nbins**3,3)) 55 | pos[:,0] = xv.flatten() 56 | pos[:,1] = yv.flatten() 57 | pos[:,2] = zv.flatten() 58 | atomss = Atoms('H'+str(nbins**3)) 59 | atomss.set_cell(atoms.get_cell())#making pseudo-crystal containing H positioned at pre-defined fractional coordinate 60 | atomss.set_pbc(True) 61 | atomss.set_scaled_positions(pos) 62 | fakeatoms_grid = atomss 63 | return fakeatoms_grid 64 | 65 | def get_image_all_atoms(atoms,nbins,scale,norm,num_cores): 66 | fakeatoms_grid = get_fakeatoms_grid(atoms,nbins) 67 | cell = atoms.get_cell() 68 | imageall_gen = Parallel(n_jobs=num_cores)(delayed(get_image_one_atom)(atom,fakeatoms_grid,nbins,scale) for atom in atoms) 69 | imageall_list = list(imageall_gen) 70 | cod_atomlist,cod_atomindex = get_atomlist_atomindex() 71 | nchannel = len(cod_atomlist) 72 | channellist = [] 73 | for i,atom in enumerate(atoms): 74 | channel = cod_atomindex[atom.symbol] 75 | channellist.append(channel) 76 | channellist = list(set(channellist)) 77 | nc = len(channellist) 78 | shape = (nbins,nbins,nbins,nc) 79 | image = numpy.zeros(shape) 80 | for i,atom in enumerate(atoms): 81 | nnc = channellist.index(cod_atomindex[atom.symbol]) 82 | img_i = imageall_list[i] 83 | image[:,:,:,nnc] += img_i * (img_i>=0.02) 84 | 85 | return image,channellist 86 | 87 | def image2pickle(image,channellist,savefilename): 88 | dic = {'image':image.tolist()} 89 | with open(savefilename,'w') as f: 90 | json.dump(dic,f) 91 | # You don't need to save channel_vector in case of making cell image 92 | 93 | def extract_cell(atoms): 94 | cell = atoms.cell 95 | atoms_ = Atoms('V') 96 | atoms_.cell = cell 97 | atoms_.set_scaled_positions([0.5,0.5,0.5]) 98 | return atoms_ 99 | 100 | def file2image(args): 101 | inputfiles = args.input_file 102 | random.shuffle(inputfiles) 103 | for inputfile in inputfiles: 104 | tmp = inputfile.split('/')[-1].split('.')[0]; tmp2 = inputfile.split('.')[0] 105 | touchfile = tmp2+'.touchtouch' 106 | filename2 = './'+tmp+'_64.pickle' 107 | savefilename = './'+tmp+'_32.npy'#'.pickle' 108 | if os.path.isfile(filename2) or os.path.isfile(savefilename): 109 | print('already made pickle') 110 | pass 111 | if os.path.isfile(touchfile): 112 | pass 113 | os.system('touch '+touchfile) 114 | try: 115 | atoms = read(inputfile,format = args.filetype) 116 | except: 117 | os.system('rm '+inputfile) 118 | continue 119 | scale = get_scale(sigma=0.26) # values for Gaussain width 120 | num_cores = args.nproc 121 | nbins = args.nbins # the number of grid for generated output image 122 | 123 | image,channellist = get_image_all_atoms(extract_cell(atoms),nbins,scale,norm,num_cores) 124 | image2pickle(image,channellist,savefilename) 125 | os.system('rm '+touchfile) 126 | return 1 127 | 128 | def main(): 129 | parser = argparse.ArgumentParser(description='mapping POSCAR or cif structure into a box image') 130 | parser.add_argument('--input_file', type=str,nargs='+', 131 | help='a file path with the poscar or cif structure') 132 | parser.add_argument('--filetype', type=str,default='cif', 133 | help='filetype : cif,vasp') 134 | parser.add_argument('--nbins', type=int,default=32, 135 | help='number of bins in one dimension') 136 | parser.add_argument('--nproc', type=int,default=1, 137 | help='number of process') 138 | 139 | args = parser.parse_args() 140 | file2image(args) 141 | return 1 142 | 143 | if __name__=='__main__': 144 | main() 145 | 146 | 147 | -------------------------------------------------------------------------------- /iMatGen-VO_dataset_generated_strctures.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaist-amsg/imatgen/35a8466cd04fb07b12218082756150a8109f0160/iMatGen-VO_dataset_generated_strctures.tar -------------------------------------------------------------------------------- /iMatGen.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaist-amsg/imatgen/35a8466cd04fb07b12218082756150a8109f0160/iMatGen.tar -------------------------------------------------------------------------------- /img2basis.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import math 5 | import glob 6 | import numpy as np 7 | from tqdm import tqdm 8 | 9 | from ase.io import read,write 10 | from ase import Atoms,Atom 11 | 12 | from scipy.ndimage import maximum_filter, gaussian_filter 13 | from scipy.ndimage.morphology import generate_binary_structure, binary_erosion 14 | 15 | def detect_peaks(image): 16 | neighborhood = generate_binary_structure(3, 2) 17 | local_max = (maximum_filter(image, footprint = neighborhood, mode = "wrap") == image) 18 | 19 | background = (image < 0.02) 20 | 21 | eroded_background = binary_erosion(background, structure = neighborhood, border_value = 1) 22 | detected_peaks = np.logical_and(local_max, np.logical_not(eroded_background)) 23 | return detected_peaks 24 | 25 | def reconstruction(image,ele): 26 | # image should have dimension of (N,N,N) 27 | image0 = gaussian_filter(image,sigma=0.15) 28 | peaks = detect_peaks(image0) 29 | 30 | recon_mat = Atoms(cell=15*np.identity(3),pbc=[1,1,1]) 31 | (peak_x,peak_y,peak_z) = np.where(peaks==1.0) 32 | for px,py,pz in zip(peak_x,peak_y,peak_z): 33 | if np.sum(image[px-3:px+4,py-3:py+4,pz-3:pz+4] > 0) >= 0: 34 | recon_mat.append(Atom(ele,(px/64.0,py/64.0,pz/64.0))) 35 | pos = recon_mat.get_positions() 36 | recon_mat.set_scaled_positions(pos) 37 | 38 | return recon_mat 39 | 40 | ele = ['O','V']; done=0; 41 | for cucum in tqdm(glob.glob('*.json')): 42 | with open(cucum) as f: 43 | dat = json.load(f) 44 | img = dat['image'] 45 | 46 | tmp_mat = [] 47 | for idc in range(2): 48 | image = img[:,:,:,idc].reshape(64,64,64) 49 | tmp_mat.append(reconstruction(image,ele[idc])) 50 | 51 | for atom in tmp_mat[-1]: 52 | tmp_mat[0].append(atom) 53 | 54 | write(cucum[:-7]+'.cif',tmp_mat[0]) 55 | -------------------------------------------------------------------------------- /img2cell.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pickle 3 | import math 4 | import glob 5 | import time 6 | 7 | from tqdm import tqdm 8 | 9 | from ase import Atom,Atoms 10 | from ase.io import write 11 | 12 | def compute_length(axis_val): 13 | non_zeros = axis_val[axis_val > 0] 14 | (a,) = np.where(axis_val == non_zeros.min()) 15 | 16 | # distance from center in grid space 17 | N = np.abs(16 - a[0]) 18 | 19 | # length of the unit vector 20 | r_fake = np.sqrt(-2*0.26**2*np.log(non_zeros.min())) #r_fake = N*(r/32) 21 | r = r_fake * 32.0 / float(N) 22 | return r 23 | 24 | def compute_angle(ri,rj,rij): 25 | cos_theta = (ri**2 + rj**2 - rij**2) / (2*ri*rj) 26 | theta = math.acos(-cos_theta) * 180/np.pi # angle in deg. 27 | return theta 28 | 29 | def define_cell(json_name): 30 | with open(json_name) as f: 31 | dat = json.load(f) 32 | img = dat['image'] 33 | 34 | img = img.reshape(32,32,32); 35 | 36 | a_axis = img[:,16,16]; ra = compute_length(a_axis) 37 | b_axis = img[16,:,16]; rb = compute_length(b_axis) 38 | c_axis = img[16,16,:]; rc = compute_length(c_axis) 39 | 40 | ab_axis = np.array([img[i,i,16] for i in range(32)]); rab = compute_length(ab_axis) 41 | bc_axis = np.array([img[16,i,i] for i in range(32)]); rbc = compute_length(bc_axis) 42 | ca_axis = np.array([img[i,16,i] for i in range(32)]); rca = compute_length(ca_axis) 43 | 44 | alpha = compute_angle(rb,rc,rbc) 45 | beta = compute_angle(rc,ra,rca) 46 | gamma = compute_angle(ra,rb,rab) 47 | 48 | atoms = Atoms(cell=[ra,rb,rc,alpha,beta,gamma],pbc=True) 49 | atoms.append(Atom('Cu',[0.5]*3)) 50 | pos = atoms.get_positions() 51 | atoms.set_scaled_positions(pos) 52 | write(pickle_name[:-7]+'.cif',atoms) 53 | 54 | for pickle_name in tqdm(glob.glob('*.json')): 55 | try: 56 | define_cell(pickle_name) 57 | except: 58 | pass 59 | --------------------------------------------------------------------------------