diff --git a/pyef/analysis.py b/pyef/analysis.py index f18c584..009b01b 100644 --- a/pyef/analysis.py +++ b/pyef/analysis.py @@ -39,6 +39,9 @@ def __init__(self, lst_of_folders, lst_of_tmcm_idx, folder_to_file_path, inGaCag self.dict_of_calcs = {'Hirshfeld': '1', 'Voronoi':'2', 'Mulliken': '5', 'Lowdin': '6', 'SCPA': '7', 'Becke': '10', 'ADCH': '11', 'CHELPG': '12', 'MK':'13', 'AIM': '14', 'Hirshfeld_I': '15', 'CM5':'16', 'EEM': '17', 'RESP': '18', 'PEOE': '19'} self.inGaCageBool = inGaCage self.dielectric = 1 + + #To avoid over-estimating screening from bound atoms, set dielectric to 1 for primary bound atoms in ESP calv + self.changeDielectBoundBool = True # Dictionary is originally from molsimplify, # Data from http://www.webelements.com/ (last accessed May 13th 2015) # Palladium covalent radius seemed to be under-estimated in original implementation, so changed to 1.39 per https://webelements.com/palladium/atom_sizes.html # Dictionary from molsimplify, https://molsimplify.readthedocs.io/en/latest/_modules/molSimplify/Classes/globalvars.html @@ -353,7 +356,7 @@ def calcNearestCageAtom(espatom_idx, charge_file): return [NearestCageAtom] - def calcesp(espatom_idx, charge_range, charge_file, dielectric): + def calcesp(self, path_to_xyz, espatom_idx, charge_range, charge_file): """ Calculate the esp @@ -364,6 +367,7 @@ def calcesp(espatom_idx, charge_range, charge_file, dielectric): Charge_file is the filepath for the .txt file containing the hirshfeld charges (generated by multiwfn) """ + dielectric = self.dielectric df = pd.read_csv(charge_file, sep='\s+', names=["Atom",'x', 'y', 'z', "charge"]) k = 8.987551*(10**9) # Coulombic constant in kg*m**3/(s**4*A**2) @@ -392,16 +396,24 @@ def calcesp(espatom_idx, charge_range, charge_file, dielectric): one_mol = 6.02*(10**23) cal_J = 4.184 + bound_atoms = [] + #create list of bound atoms, these are treated with a different dielectric + if self.changeDielectBoundBool: + bound_atoms = self.getBondedAtoms(path_to_xyz, idx_atom) + for idx in charge_range: if idx == idx_atom: continue + elif idx in bound_atoms: + #now account for bound atoms + r = (((xs[idx] - xo)*A_to_m)**2 + ((ys[idx] - yo)*A_to_m)**2 + ((zs[idx] - zo)*A_to_m)**2)**(0.5) + total_esp = total_esp + (charges[idx]/r) else: # Calculate esp and convert to units (A to m) r = (((xs[idx] - xo)*A_to_m)**2 + ((ys[idx] - yo)*A_to_m)**2 + ((zs[idx] - zo)*A_to_m)**2)**(0.5) - total_esp = total_esp + (charges[idx]/r) + total_esp = total_esp + (1/dielectric)*(charges[idx]/r) - final_esp = k*total_esp*((C_e))*cal_J*faraday*(1/dielectric) # Note: cal/kcal * kJ/J gives 1 - # print(str(final_esp) + ' kJ/(mol*e)') + final_esp = k*total_esp*((C_e))*cal_J*faraday # Note: cal/kcal * kJ/J gives 1 return [final_esp, df['Atom'][idx_atom]] @@ -571,7 +583,7 @@ def E_proj_first_coord(self, metal_idx, xyz_file_path, atom_multipole_file): def esp_first_coord(self, metal_idx, charge_file, path_to_xyz): print('The index of the metal atom is: ' + str(metal_idx)) lst_bonded_atoms = self.getBondedAtoms(path_to_xyz, metal_idx) - [First_coord_ESP, atom_type] = Electrostatics.calcesp(metal_idx, lst_bonded_atoms, charge_file, self.dielectric) + [First_coord_ESP, atom_type] = self.calcesp(path_to_xyz, metal_idx, lst_bonded_atoms, charge_file) return First_coord_ESP def esp_second_coord(self, metal_idx, charge_file, path_to_xyz): @@ -583,8 +595,7 @@ def esp_second_coord(self, metal_idx, charge_file, path_to_xyz): lst_first_and_second.extend(second_coor) set_second_coor = set(lst_first_and_second) final_lst = list(set_second_coor) - final_lst.remove(metal_idx) - [second_coord_ESP, atom_type] = Electrostatics.calcesp(metal_idx, final_lst, charge_file, self.dielectric) + [second_coord_ESP, atom_type] = self.calcesp(path_to_xyz, metal_idx, final_lst, charge_file) return second_coord_ESP # Boolean CageTrue @@ -599,18 +610,19 @@ def charge_atom(filename, atom_idx): partial_charge_atom = charges[atom_idx] return [total_charge, partial_charge_atom] - def ESP_all_calcs(filename, atom_idx, cageTrue, dlc): + def ESP_all_calcs(self, path_to_xyz, filename, atom_idx, cageTrue): # Get the number of lines in the txt file + dlc = self.dielectric total_lines =Electrostatics.mapcount(filename) all_lines = range(0, total_lines) - [ESP_all, atom_type] = Electrostatics.calcesp(atom_idx, all_lines, filename, dlc) + [ESP_all, atom_type] = self.calcesp(path_to_xyz, atom_idx, all_lines, filename) if cageTrue: cage_lines = range(0, 280) guest_lines = range(280, total_lines) # print('Cage indices: ' + str(cage_lines)) # print('Guest indices: ' + str(guest_lines)) - ESP_just_ligand = Electrostatics.calcesp(atom_idx, guest_lines, filename, dlc)[0] - ESP_just_cage = Electrostatics.calcesp(atom_idx, cage_lines, filename, dlc)[0] + ESP_just_ligand = self.calcesp(path_to_xyz, atom_idx, guest_lines, filename)[0] + ESP_just_cage = self.calcesp(path_to_xyz, atom_idx, cage_lines, filename)[0] print('ESP for all atoms: ' + str(ESP_all) + ' kJ/(mol*e)') print('ESP just ligand: ' + str(ESP_just_ligand) + ' kJ/(mol*e)') print('ESP just cage: ' + str(ESP_just_cage) + ' kJ/(mol*e)') @@ -620,7 +632,8 @@ def ESP_all_calcs(filename, atom_idx, cageTrue, dlc): return [ESP_all, atom_type] - def esp_bydistance(espatom_idx, charge_file, dielectric): + def esp_bydistance(self, path_to_xyz, espatom_idx, charge_file): + dielectric = self.dielectric df = pd.read_csv(charge_file, sep='\s+', names=["Atom",'x', 'y', 'z', "charge"]) k = 8.987551*(10**9) # Coulombic constant in kg*m**3/(s**4*A**2) @@ -653,9 +666,16 @@ def esp_bydistance(espatom_idx, charge_file, dielectric): total_atoms = len(xs) distances = [] esps = [] + bound_atoms = [] + if self.changeDielectBoundBool: + bound_atoms = self.getBondedAtoms(path_to_xyz, idx_atom) for idx in range(0, total_atoms): if idx == idx_atom: continue + elif idx in bound_atoms: + r = (((xs[idx] - xo)*A_to_m)**2 + ((ys[idx] - yo)*A_to_m)**2 + ((zs[idx] - zo)*A_to_m)**2)**(0.5) + esps.append(k**C_e*cal_J*faraday*charges[idx]/r) + distances.append(r) else: r = (((xs[idx] - xo)*A_to_m)**2 + ((ys[idx] - yo)*A_to_m)**2 + ((zs[idx] - zo)*A_to_m)**2)**(0.5) distances.append(r) @@ -744,12 +764,12 @@ def getESPData(self, charge_types, ESPdata_filename): try: if self.inGaCageBool: # With newly analyzed partial charges, re-compute ESP data - [ESP_all, ESP_just_ligand, ESP_just_cage, atom_type] = Electrostatics.ESP_all_calcs(full_file_path, atom_idx, self.inGaCageBool, self.dielectric) + [ESP_all, ESP_just_ligand, ESP_just_cage, atom_type] = self.ESP_all_calcs(path_to_xyz, full_file_path, atom_idx, self.inGaCageBool) else: - [ESP_all, atom_type] = Electrostatics.ESP_all_calcs(full_file_path, atom_idx, self.inGaCageBool, self.dielectric) + [ESP_all, atom_type] = self.ESP_all_calcs(path_to_xyz, full_file_path, atom_idx, self.inGaCageBool) [total_charge,partial_charge_atom] = Electrostatics.charge_atom(full_file_path, atom_idx) - [sorted_distances, sorted_esps, cum_esps] = Electrostatics.esp_bydistance(atom_idx, full_file_path, self.dielectric) + [sorted_distances, sorted_esps, cum_esps] = self.esp_bydistance(path_to_xyz, atom_idx, full_file_path) ESP_fcoord = self.esp_first_coord(atom_idx, full_file_path, path_to_xyz) ESP_scoord = self.esp_second_coord(atom_idx, full_file_path, path_to_xyz) @@ -770,12 +790,12 @@ def getESPData(self, charge_types, ESPdata_filename): if self.inGaCageBool: # With newly analyzed partial charges, re-compute ESP data - [ESP_all, ESP_just_ligand, ESP_just_cage, atom_type] = Electrostatics.ESP_all_calcs(full_file_path, atom_idx, self.inGaCageBool) + [ESP_all, ESP_just_ligand, ESP_just_cage, atom_type] = self.ESP_all_calcs(path_to_xyz, full_file_path, atom_idx, self.inGaCageBool) else: - [ESP_all, atom_type] = Electrostatics.ESP_all_calcs(full_file_path, atom_idx, self.inGaCageBool) + [ESP_all, atom_type] = self.ESP_all_calcs(full_file_path, atom_idx, self.inGaCageBool) [total_charge,partial_charge_atom] = Electrostatics.charge_atom(full_file_path, atom_idx) - [sorted_distances, sorted_esps, cum_esps] = Electrostatics.esp_bydistance(atom_idx, full_file_path) + [sorted_distances, sorted_esps, cum_esps] = self.esp_bydistance(path_to_xyz, atom_idx, full_file_path) ESP_fcoord = self.esp_first_coord(atom_idx, full_file_path, path_to_xyz) ESP_scoord = self.esp_second_coord(atom_idx, full_file_path, path_to_xyz)