def main(): print( "WARNING! The partial g(r)'s in this function might be a bit off (compared to RINGS calculations). Also, the total is a bit off too. However, if you add up all the partials you DO get the correct total (assuming RINGS is right)." ) modelfile = sys.argv[1] m = Model(modelfile) # This block of code prints the cutoffs cutoffs = generate_cutoffs(m) print(cutoffs) # This block of code saves all the gr's to gr.txt outcontent = [] types = list(m.atomtypes) for L in range(1, len(types) + 1): for subset in itertools.combinations(types, L): print(subset) s = list(subset) x, g = gr(m, types=s) g = list(g) s = [znum2sym.z2sym(y) for y in s] g.insert(0, "gr_{0}".format("_".join(s))) outcontent.append(g) print("Writing output to gr.txt.") x = list(x) x.insert(0, "dr") outcontent.insert(0, x) outcontent = [[str(y) for y in x] for x in zip(*outcontent)] of = open("gr.txt", "w") for i in xrange(0, len(outcontent)): of.write(" ".join(outcontent[i]) + "\n")
def index_stats(m): """ Prints the number of atoms in each VP index""" cats = {} for atom in m.atoms: #if atom.sym == 'Zr' or atom.sym == 'Al': continue #if atom.sym == 'Zr' or atom.sym == 'Cu': continue if atom.vp.index not in cats: cats[atom.vp.index] = OrderedDict() for typ in sorted([z2sym(x) for x in m.atomtypes], reverse=True): cats[atom.vp.index][typ] = 0 cats[atom.vp.index][atom.sym] = cats[atom.vp.index].get(atom.sym,0) + 1 cats[atom.vp.index]["Total"] = cats[atom.vp.index].get("Total",0) + 1 # Print for val,key in sorted( ((v,k) for k,v in cats.iteritems()), key=lambda t: t[0]['Total']): #for atom in m.atoms: # if(atom.vp.index == key): # typ = atom.vp.type # break #print("{0}: \t{1}\t{2}".format(key,val,typ)) #if list(key)[0:4] != [0,2,8,0]: # continue if val['Total'] < m.natoms*0.005: continue val = [(k,value) for k,value in val.items()] val = [str(x) for row in val for x in row] val = '\t'.join(val) print("{0}: \t{1}".format(key,val)) #print("{0}: \t{1}\t{2}".format(key,val,round(val['Total']/float(m.natoms)*100,3))) return cats
def index_stats(self): cats = {} for atom in self.m.atoms: if atom.vp.index not in cats: cats[atom.vp.index] = OrderedDict() for typ in sorted([z2sym(x) for x in self.m.atomtypes], reverse=True): cats[atom.vp.index][typ] = 0 cats[atom.vp.index][atom.sym] = cats[atom.vp.index].get(atom.sym, 0) + 1 cats[atom.vp.index]["Total"] = cats[atom.vp.index].get("Total", 0) + 1 return cats
def __init__(self, id, znum, x, y, z): self.id = id if(isinstance(znum,int)): self.z = znum elif(isinstance(znum,str)): self.z = znum2sym.sym2z(znum) self.coord = (x,y,z) self.vp = VoronoiPoly() self.neighs = None # Neighbors. List when set self.cn = None # Coordination number. int when set self.sym = znum2sym.z2sym(self.z) #atomic symbol
def _write_cif(self, outfile=None): if outfile is None: of = sys.stdout else: of = open(outfile,'w') of.write('_pd_phase_name\t'+self.comment+'\n') of.write('_cell_length_a '+str(self.xsize)+'\n') of.write('_cell_length_b '+str(self.ysize)+'\n') of.write('_cell_length_c '+str(self.zsize)+'\n') of.write('_cell_angle_alpha 90\n_cell_angle_beta 90\n_cell_angle_gamma 90\n') of.write('_symmetry_space_group_name_H-M \'P 1\'\n_symmetry_Int_Tables_number 1\n\n') of.write('loop_\n_symmetry_equiv_pos_as_xyz\n \'x, y, z\'\n\n') of.write('loop_\n _atom_site_label\n _atom_site_occupancy\n _atom_site_fract_x\n _atom_site_fract_y\n _atom_site_fract_z\n _atom_site_adp_type\n _atom_site_B_iso_or_equiv\n _atom_site_type_symbol\n') atomtypes = {} for atom in self.atoms: atomtypes[atom.z] = atomtypes.get(atom.z, 0) + 1 of.write(' '+znum2sym.z2sym(atom.z)+str(atomtypes[atom.z])+'\t1.0\t'+str(atom.coord[0]/self.xsize+0.5)+'\t'+str(atom.coord[1]/self.ysize+0.5)+'\t'+str(atom.coord[2]/self.zsize+0.5)+'\tBiso\t1.000000\t'+znum2sym.z2sym(atom.z)+'\n') of.write('\n') of.close()
def generate_cutoffs(m): outcontent = [] cutoff_types = [] types = list(m.atomtypes) types.sort() for L in range(1, len(types)): # for L in range(1,len(types)+1): for subset in itertools.combinations(types, L): # print(subset) s = list(subset) xx, g = gr(m, types=s) g = list(g) s = [znum2sym.z2sym(y) for y in s] # g.insert(0,'gr_{0}'.format('_'.join(s))) outcontent.append(g) cutoff_types.append(s) cutoff_types = [[x[0], x[0]] if len(x) == 1 else x for x in cutoff_types] cutoff_types = [[znum2sym.sym2z(y) for y in x] for x in cutoff_types] cutoff_types = [[types.index(y) for y in x] for x in cutoff_types] # print(cutoff_types) cutoffs = np.zeros((len(m.atomtypes), len(m.atomtypes))) xx = list(xx) # xx.insert(0,'dr') outcontent.insert(0, xx) for i, arr in enumerate(outcontent[1:]): peak1 = arr.index(max(arr)) # print('peak1',peak1,xx[peak1],arr[peak1]) # print(arr[peak1:int(round(peak1*3.5))]) min1 = peak1 + arr[peak1 : int(round(peak1 * 3.5))].index(min(arr[peak1 : int(round(peak1 * 3.5))])) # print('min1',min1,xx[min1],arr[min1]) peak2 = min1 + arr[min1:].index(max(arr[min1:])) # print('peak2',peak2,xx[peak2],arr[peak2]) # print('') cutoffs[cutoff_types[i][0]][cutoff_types[i][1]] = xx[min1] cutoffs[cutoff_types[i][1]][cutoff_types[i][0]] = xx[min1] # print(cutoffs) return cutoffs
def __add__(self, other): if isinstance(other, Model): self.natoms += other.natoms cats = self.indices for atom in other.atoms: if atom.vp.index not in cats: cats[atom.vp.index] = OrderedDict() for typ in sorted([z2sym(x) for x in other.atomtypes], reverse=True): cats[atom.vp.index][typ] = 0 cats[atom.vp.index][atom.sym] = cats[atom.vp.index].get(atom.sym, 0) + 1 cats[atom.vp.index]["Total"] = cats[atom.vp.index].get("Total", 0) + 1 cats = self.categories for atom in other.atoms: if atom.vp.type not in cats: cats[atom.vp.type] = {} cats[atom.vp.type][atom.sym] = cats[atom.vp.type].get(atom.sym, 0) + 1 cats[atom.vp.type]["Total"] = cats[atom.vp.type].get("Total", 0) + 1 # elif isinstance(other, VPStatistics): else: raise Exception("Cannot add type {0} to VPStatistics!".format(type(other))) return self
def generate_coord_numbers(self): """ atom.neighs must be defined first for all atoms """ self.coord_numbers = {} # Form will be: # {'Cu-Al': 4.5}, etc. for typea in self.atomtypes: self.coord_numbers[znum2sym.z2sym(typea)] = 0 for typeb in self.atomtypes: self.coord_numbers[znum2sym.z2sym(typea)+'-'+znum2sym.z2sym(typeb)] = 0 for atom in self.atoms: for n in atom.neighs: self.coord_numbers[znum2sym.z2sym(atom.z)] += 1 self.coord_numbers[znum2sym.z2sym(atom.z)+'-'+znum2sym.z2sym(n.z)] += 1 self.bonds = self.coord_numbers.copy() for key in self.coord_numbers: elem = znum2sym.sym2z(key.split('-')[0]) self.coord_numbers[key] /= float(self.atomtypes[elem])
def radial_composition(self, outfile): """ Creates 1D waves stored in outfile for each element in the model. Each wave is a histogram of the number of atoms between two radial positions starting at the center of model and radiating outward. """ # TODO Rewrite if I ever need this again npix = 16 keys = self.atomtypes.keys() #histo = [[0.0 for x in range(npix)] for key in keys] histo = [{} for x in range(npix)] dx = (self.xsize/2.0)/npix # Cube assumed for i,r in enumerate(drange(dx, npix*dx-dx, dx)): atoms = self.get_atoms_in_cutoff( (0.0,0.0,0.0), r) print(r, len(atoms)) comp = {} for atom in atoms: comp[str(atom.z)] = comp.get(str(atom.z),0) + 1.0 for type in self.atomtypes: if( str(type) not in comp.keys()): comp[str(type)] = 0.0 comp['Total'] = len(atoms) histo[i] = comp of = open(outfile,'w') of.write('IGOR\n') for atomtype in keys: of.write('\nWAVES/N=({0})\t {1}\nBEGIN\n'.format(npix,'partial_radial_comp_'+znum2sym.z2sym(atomtype))) for i in range(npix-2): if(i != 0): of.write("{0} ".format((histo[i][str(atomtype)] - histo[i-1][str(atomtype)])/( 4.0/3.0*np.pi*( (i*dx)**3 - ((i-1)*dx)**3 )))) #print("{1} {0} ".format(histo[i][str(atomtype)],i*dx)) #print(" {1} {0} ".format(histo[i][str(atomtype)] - histo[i-1][str(atomtype)],i*dx)) else: of.write("{0} ".format(histo[i][str(atomtype)])) #print("{1} {0} ".format(histo[i][str(atomtype)],i*dx)) of.write("\n") of.write('END\n') of.write('X SetScale x 0,{1}, {0};\n'.format('partial_comp_'+znum2sym.z2sym(atomtype),npix*dx-dx)) of.close()
def generate_average_coord_numbers(self): """ atom.neighs must be defined first for all atoms Form will be: {'Cu-Al': 4.5, ... } """ coord_numbers = {} for typea in self.atomtypes: coord_numbers[znum2sym.z2sym(typea)] = 0 for typeb in self.atomtypes: coord_numbers[znum2sym.z2sym(typea)+'-'+znum2sym.z2sym(typeb)] = 0 for atom in self.atoms: for n in atom.neighs: coord_numbers[znum2sym.z2sym(atom.z)] += 1 coord_numbers[znum2sym.z2sym(atom.z)+'-'+znum2sym.z2sym(n.z)] += 1 for key in coord_numbers: elem = znum2sym.sym2z(key.split('-')[0]) coord_numbers[key] /= float(self.atomtypes[elem]) return coord_numbers
def local_composition(self, outfile): """ Variable radius sliding average Goes pixel by pixel and calculates the composition around that pixel (within some radius) and assigns the center pixel that composition. Use a 256 x 256 x 256 matrix. """ # TODO Rewrite if I ever need this again radius = 3.6 * 2 npix = 64 #mat = np.zeros((npix,npix,npix),dtype=np.float) #mat = np.zeros((npix,npix,npix),dtype={'names':['col1', 'col2', 'col3'], 'formats':['f4','f4','f4']}) #mat = np.zeros((npix,npix,npix),dtype={'names':['40', '13', '29'], 'formats':['f4','f4','f4']}) #mat = np.zeros((npix,npix,npix),dtype={'names':['id','data'], 'formats':['f4','f4']}) #names = ['id','data'] #formats = ['i4',('f4','f4','f4')] #mat = np.zeros((npix,npix,npix),dtype=dict(names = names, formats=formats)) #mat = np.zeros((npix,npix,npix),dtype={'40':('i4',0), '29':('f4',0), '13':('f4',0)}) print("Creating matrix...") mat = [[[{} for i in range(npix)] for j in range(npix)] for k in range(npix)] print("Finished creating matrix.") #print(repr(mat)) dx = self.xsize/npix dy = self.ysize/npix dz = self.zsize/npix for ii,i in enumerate(drange(-npix/2*dx,npix/2*dx-dx,dx)): print("On ii = {0}".format(ii)) for jj,j in enumerate(drange(-npix/2*dy,npix/2*dy-dy,dy)): for kk,k in enumerate(drange(-npix/2*dz,npix/2*dz-dz,dz)): atoms = self.get_atoms_in_cutoff( (i,j,k), radius ) comp = {} for atom in atoms: comp[str(atom.z)] = comp.get(str(atom.z),0) + 1.0 for key in comp: comp[key] /= len(atoms) #print(comp) #mat[ii][jj][kk] = copy.copy(comp) mat[ii][jj][kk] = comp of = open(outfile,'w') of.write('IGOR\n') for atomtype in self.atomtypes: of.write('\nWAVES/N=({0},{1},{2})\t {3}\nBEGIN\n'.format(npix,npix,npix,'partial_comp_'+znum2sym.z2sym(atomtype))) for layer in mat: for column in layer: for value in column: try: of.write("{0} ".format(value[str(atomtype)])) except KeyError: of.write("{0} ".format(0.0)) of.write("\n") of.write('END\n') of.write('X SetScale/P x 0,1,"", {0}; SetScale/P y 0,1,"", {0}; SetScale/P z 0,1,"", {0}; SetScale d 0,0,"", {0}\n'.format('partial_comp_'+znum2sym.z2sym(atomtype))) of.close() return mat
def composition(self): d = {} for key in self.atomtypes: d[znum2sym.z2sym(key)] = self.atomtypes[key]/float(self.natoms) return d
def convert_to_sym(self): self.z = znum2sym.z2sym(self.z) return self
def realxyz(self): return str(znum2sym.z2sym(self.z))+'\t'+str(self.coord[0])+'\t'+str(self.coord[1])+'\t'+str(self.coord[2])
def vesta(self): """ returns a string with the atoms information in the format for the vesta input file """ if(type(self.z) != type('hi')): return znum2sym.z2sym(self.z) + '\t' + str(self.coord[0]) + '\t' + str(self.coord[1]) + '\t' + str(self.coord[2]) elif(type(self.z) == type('hi')): return self.z + '\t' + str(self.coord[0]) + '\t' + str(self.coord[1]) + '\t' + str(self.coord[2])