def analyse_bonds(model, A, B): ''' Check A-B distances present in the model. model: Atoms object or string. If string it will read a file in the same folder, e.g. "name.traj" A: string, chemical symbol, e.g. "H" B: string, chemical symbol, e.g. "H" ''' # Read file or Atoms object if isinstance(model, str) is True: model = read(model) analysis = Analysis(model) dash = "-" * 40 print_AB = A + "-" + B # Retrieve bonds and values AB_Bonds = analysis.get_bonds(A, B) AB_BondsValues = analysis.get_values(AB_Bonds) # Table header print(dash) print(print_AB+" Distance / Angstrom") print(dash) print('{:<6.5s}{:>4.10s}{:^13.10s}{:>4.10s}'.format( "count", "average", "minimum", "maximum")) # Table contents print('{:<6.0f}{:>4.6f}{:^12.6f}{:>4.6f}'.format( len(AB_BondsValues[0]), np.average(AB_BondsValues), np.amin(AB_BondsValues), np.amax(AB_BondsValues)))
def search_abnormal_bonds(model): ''' Check all bond lengths in the model for abnormally short ones, ie. less than 0.74 Angstrom. model: Atoms object or string. If string it will read a file in the same folder, e.g. "name.traj" ''' # Combination as AB = BA for bonds, avoiding redundancy from itertools import combinations_with_replacement # Read file or Atoms object if isinstance(model, str) is True: model = read(model) # Define lists of variables abnormal_bonds = [] list_of_abnormal_bonds = [] analysis = Analysis(model) # set() to ensure unique chemical symbols list list_of_symbols = list(set(model.get_chemical_symbols())) all_bonds = combinations_with_replacement(list_of_symbols, 2) # Iterate over all arrangements of chemical symbols for bonds in all_bonds: A = bonds[0] B = bonds[1] print_AB = A+'-'+B AB_Bonds = analysis.get_bonds(A, B) # Make sure bond exist before retrieving values if not AB_Bonds == [[]]: AB_BondsValues = analysis.get_values(AB_Bonds) for i in range(0, len(AB_BondsValues)): for values in AB_BondsValues[i]: if values < 0.74: abnormal_bonds += [1] list_of_abnormal_bonds = list_of_abnormal_bonds + [print_AB] # Abnormality check if not len(abnormal_bonds) == 0: print("A total of", len(abnormal_bonds), "abnormal bond lengths observed (<0.74 A).") print("Identities:", list_of_abnormal_bonds) else: print("OK")
def analyse_all_bonds(model): ''' Returns a table of bond distance analysis for the supplied model. Parameters: model: Atoms object or string. If string it will read a file in the same folder, e.g. "name.traj" ''' # Combination as AB = BA for bonds, avoiding redundancy from itertools import combinations_with_replacement # Read file or Atoms object if isinstance(model, str) is True: model = read(model) analysis = Analysis(model) dash = "-" * 40 # set() to ensure unique chemical symbols list list_of_symbols = list(set(model.get_chemical_symbols())) all_bonds = combinations_with_replacement(list_of_symbols, 2) # Table heading print(dash) print('{:<6.5s}{:<6.5s}{:>4.10s}{:^13.10s}{:>4.10s}'.format( "Bond", "Count", "Average", "Minimum", "Maximum")) print(dash) # Iterate over all arrangements of chemical symbols for bonds in all_bonds: A = bonds[0] B = bonds[1] print_AB = A + '-' + B AB_Bonds = analysis.get_bonds(A, B) # Make sure bond exist before retrieving values, then print contents if not AB_Bonds == [[]]: AB_BondsValues = analysis.get_values(AB_Bonds) print('{:<8.8s}{:<6.0f}{:>4.6f}{:^12.6f}{:>4.6f}'.format( print_AB, len(AB_BondsValues[0]), np.average(AB_BondsValues), np.amin(AB_BondsValues), np.amax(AB_BondsValues)))
def analyse_bonds(model, A, B, verbose=True, multirow=False): ''' Check A-B distances present in the model. Parameters: model: Atoms object XXX A: string, chemical symbol, e.g. "H" B: string, chemical symbol, e.g. "H" verbose: Boolean Whether to print information to screen multirow: Boolean Whether we are working with analyse_all_bonds, so the output is multirow, or just one specific analysis of a bond, in which case the table header is needed. ''' from ase.geometry.analysis import Analysis analysis = Analysis(model) print_AB = A + "-" + B # Retrieve bonds and values AB_Bonds = analysis.get_bonds(A, B) if AB_Bonds == [[]]: AB_BondsValues = None else: AB_BondsValues = analysis.get_values(AB_Bonds) if verbose and AB_BondsValues is not None: if not multirow: print_bond_table_header() # Table contents import numpy as np print('{:<8.8s}{:<6.0f}{:>4.6f}{:^12.6f}{:>4.6f}'.format( print_AB, len(AB_BondsValues[0]), np.average(AB_BondsValues), np.amin(AB_BondsValues), np.amax(AB_BondsValues))) return print_AB, AB_Bonds, AB_BondsValues
AllSnIAngles = [] AllPbIPbAngles = [] AllSnISnAngles = [] for i in range(0, 16): # VASP POSCAR PEA2PbSnI4 = read('CONTCAR_PbSn' + str(i)) #print(PEA2PbSnI4) ana = Analysis(PEA2PbSnI4) # Bonds PbIBonds = ana.get_bonds('Pb', 'I', unique=True) SnIBonds = ana.get_bonds('Sn', 'I', unique=True) #print("\nThere are {} Pb-I bonds in PEA2PbSnI4.".format(len(PbIBonds[0]))) #print("There are {} Pb-I bonds in PEA2PbSnI4.".format(len(SnIBonds[0]))) if len(PbIBonds[0]) > 0: PbIBondValues = ana.get_values(PbIBonds) if len(SnIBonds[0]) > 0: SnIBondValues = ana.get_values(SnIBonds) #print("The average Pb-I bond length is {}.".format(np.average(PbIBondValues))) #print("The average Sn-I bond length is {}.".format(np.average(SnIBondValues))) if len(PbIBonds[0]) > 0:
def search_abnormal_bonds(model, verbose=True): ''' Check all bond lengths in the model for abnormally short ones, ie. less than 0.74 Angstrom. Parameters: model: Atoms object or string. If string it will read a file in the same folder, e.g. "name.traj" ''' # Combination as AB = BA for bonds, avoiding redundancy from itertools import combinations_with_replacement # Imports necessary to work out accurate minimum bond distances from ase.data import chemical_symbols, covalent_radii # Read file or Atoms object if isinstance(model, str) is True: model = read(model) # Define lists of variables abnormal_bonds = [] list_of_abnormal_bonds = [] analysis = Analysis(model) # set() to ensure unique chemical symbols list list_of_symbols = list(set(model.get_chemical_symbols())) all_bonds = combinations_with_replacement(list_of_symbols, 2) # Iterate over all arrangements of chemical symbols for bonds in all_bonds: A = bonds[0] B = bonds[1] # For softcoded bond cutoff sum_of_covalent_radii = covalent_radii[chemical_symbols.index( A)] + covalent_radii[chemical_symbols.index(B)] print_AB = A + '-' + B AB_Bonds = analysis.get_bonds(A, B) # Make sure bond exist before retrieving values if not AB_Bonds == [[]]: AB_BondsValues = analysis.get_values(AB_Bonds) for i in range(0, len(AB_BondsValues)): for values in AB_BondsValues[i]: # TODO: move the 75% of sum_of_covalent_radii before the loops if values < max(0.4, sum_of_covalent_radii * 0.75): abnormal_bonds += [1] list_of_abnormal_bonds = list_of_abnormal_bonds + [ print_AB ] # Abnormality check # is it possible to make a loop with different possible values instead of 0.75 and takes the average if len(abnormal_bonds) > 0: if verbose: print( "A total of", len(abnormal_bonds), "abnormal bond lengths observed (<" + str(max(0.4, sum_of_covalent_radii * 0.75)) + " A).") print("Identities:", list_of_abnormal_bonds) return False else: if verbose: print("OK") return True
from ase.io.trajectory import Trajectory import numpy as np from ase.io import read from ase.geometry.analysis import Analysis #old file see bonds.py for better version file = read('tin_acetate.xyz') traj = Trajectory('tin_acetate.traj', 'w') traj.write(file) file = read('tin_acetate.traj') ana = Analysis(file) SiOBonds = ana.get_bonds('Sn', 'O') SiOSiAngles = ana.get_angles('O', 'Sn', 'O') print("there are {} Si-O bonds in BETA".format(len(SiOBonds[0]))) print("there are {} Si-O-Si angles in BETA".format(len(SiOSiAngles[0]))) SiOBondsValues = ana.get_values(SiOBonds) SiOSiAngleValues = ana.get_values(SiOSiAngles) print("bond length data:") print("the average Si-O bond length is {}.".format(np.average(SiOBondsValues))) print("the minimum Si-O Distance is:", np.amin(SiOBondsValues)) print("the maximum Si-O Distance is:", np.amax(SiOBondsValues)) print("bond angle data:") print("the average Si-O-Si angle is {}.".format(np.average(SiOSiAngleValues))) print("the maximum Si-O-Si angle is:", np.amax(SiOSiAngleValues)) print("the minimum Si-O-Si angle is:", np.amin(SiOSiAngleValues))