def lewis2xyz(lewis,f='SMILES',aromatic=False,dim=2,addH=True): # Input # lewis ... smiles format string # aromatic ... is the system aromatic # dim ... 2d == 2 and 3d == 3 # Output # Bonding information # Lewis pictures # sdf and xyz files if f == 'pdb': m = Chem.MolFromPDBFile(lewis) if f == 'xyz': struct = read(lewis) write('lewis.pdb',struct,'proteindatabank') m = Chem.MolFromPDBFile(lewis) if f == 'SMILES': m = Chem.MolFromSmiles(lewis) # Change armatic bonds to alternate single and double bonds if aromatic == True: if m.GetBondWithIdx(0).GetIsAromatic() == True: Chem.Kekulize(m) if addH == True: m=Chem.AddHs(m) if dim == 1 or dim == 2: AllChem.Compute2DCoords(m) if dim == 3: AllChem.EmbedMolecule(m) AllChem.UFFOptimizeMolecule(m) fods = Atoms() # core electrons for atom in m.GetAtoms(): idx = atom.GetIdx() # atomic number N = m.GetAtomWithIdx(idx).GetAtomicNum() # number of valence electrons V = m.GetAtomWithIdx(idx).GetTotalValence() # number of radicals R = atom.GetNumRadicalElectrons() # formal charge of the atom F = atom.GetFormalCharge() # number of core electrons C = N-V-R-F # lone pairs #L = 0 #bonds = atom.GetBonds() #for b in range(len(bonds)): # bond_type = bonds[b].GetBondType() # if str(bond_type) == 'SINGLE': # L = L + 1 # if str(bond_type) == 'DOUBLE': # L = L + 2 # if str(bond_type) == 'TRIPLE': # L = L + 3 #print(V-L) if C > 0: pos = m.GetConformer().GetAtomPosition(idx) offset = 0.002 if C == 1: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) if C == 2: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]+offset])) if C == 3: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]+offset])) fods.append(Atom('X',[pos[0]+offset,pos[1]+offset,pos[2]+4*offset])) if C == 4: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]+offset])) fods.append(Atom('X',[pos[0]+offset,pos[1]+offset,pos[2]+40*offset])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]-40*offset])) if C == 5: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]+offset])) fods.append(Atom('X',[pos[0]+offset,pos[1]+offset,pos[2]+40*offset])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]-40*offset])) fods.append(Atom('X',[pos[0]+40*offset,pos[1]+40*offset,pos[2]+offset])) if C == 6: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]+offset])) fods.append(Atom('X',[pos[0]+40*offset,pos[1]+40*offset,pos[2]+40*offset])) fods.append(Atom('He',[pos[0]+offset,pos[1]-40*offset,pos[2]-40*offset])) fods.append(Atom('X',[pos[0]-40*offset,pos[1]+40*offset,pos[2]-40*offset])) fods.append(Atom('He',[pos[0]-40*offset,pos[1]-40*offset,pos[2]+40*offset])) if C == 7: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]+offset])) fods.append(Atom('X',[pos[0]+40*offset,pos[1]+40*offset,pos[2]+40*offset])) fods.append(Atom('He',[pos[0]+offset,pos[1]-40*offset,pos[2]-40*offset])) fods.append(Atom('X',[pos[0]-40*offset,pos[1]+40*offset,pos[2]-40*offset])) fods.append(Atom('He',[pos[0]-40*offset,pos[1]-40*offset,pos[2]+40*offset])) fods.append(Atom('He',[pos[0]+42*offset,pos[1]+42*offset,pos[2]+42*offset])) if C == 8: fods.append(Atom('X',[pos[0],pos[1],pos[2]])) fods.append(Atom('He',[pos[0]+offset,pos[1]+offset,pos[2]+offset])) fods.append(Atom('X',[pos[0]+40*offset,pos[1]+40*offset,pos[2]+40*offset])) fods.append(Atom('He',[pos[0]+40*offset,pos[1]-40*offset,pos[2]-40*offset])) fods.append(Atom('X',[pos[0]-40*offset,pos[1]+40*offset,pos[2]-40*offset])) fods.append(Atom('He',[pos[0]-40*offset,pos[1]-40*offset,pos[2]+40*offset])) fods.append(Atom('He',[pos[0]+42*offset,pos[1]+42*offset,pos[2]+42*offset])) fods.append(Atom('X',[pos[0]+42*offset,pos[1]-42*offset,pos[2]-42*offset])) # find radicals for atom in m.GetAtoms(): rad = atom.GetNumRadicalElectrons() #print(rad) if rad == 1: idx = atom.GetIdx() pos = m.GetConformer().GetAtomPosition(idx) bonds = atom.GetBonds() vec_BA_x = 0 vec_BA_y = 0 vec_BA_z = 0 BA = [] for b in range(len(bonds)): ai = bonds[b].GetBeginAtomIdx() aj = bonds[b].GetEndAtomIdx() bond_type = bonds[b].GetBondType() # Positions pos_ai = m.GetConformer().GetAtomPosition(ai) pos_aj = m.GetConformer().GetAtomPosition(aj) # adding bonding vectors for 3d vec_BA_x = vec_BA_x + (pos_aj[0]-pos_ai[0]) vec_BA_y = vec_BA_y + (pos_aj[1]-pos_ai[1]) vec_BA_z = vec_BA_z + (pos_aj[2]-pos_ai[2]) # save bonding vectors for 2d BA.append(np.array([(pos_aj[0]-pos_ai[0]),(pos_aj[1]-pos_ai[1]),(pos_aj[2]-pos_ai[2])])) if dim == 1: fods.append(Atom('X',[-1*BA[0][0],-1*BA[0][1],-1*BA[0][2]])) if dim == 2: vec = np.cross(BA[0],BA[1]) norm = np.sqrt(vec[0]**2 + vec[1]**2 + vec[2]**2) pos = vec/norm fods.append(Atom('X',[pos[0],pos[1],pos[2]])) if dim == 3: norm = np.sqrt(vec_BA_x**2 + vec_BA_y**2 + vec_BA_z**2) pos = np.array([-1*vec_BA_x,-1*vec_BA_y,-1*vec_BA_z])/norm fods.append(Atom('X',[pos[0],pos[1],pos[2]])) bonds = m.GetBonds() for b in range(len(bonds)): ai = bonds[b].GetBeginAtomIdx() aj = bonds[b].GetEndAtomIdx() bond_type = bonds[b].GetBondType() # Positions pos_ai = m.GetConformer().GetAtomPosition(ai) pos_aj = m.GetConformer().GetAtomPosition(aj) # Bondlength #print('%0.5f' % np.linalg.norm([pos_ai[0]-pos_aj[0],pos_ai[1]-pos_aj[1],pos_ai[2]-pos_aj[2]])) # Middle of the vector MP = [(pos_ai[0]+pos_aj[0])/2.,(pos_ai[1]+pos_aj[1])/2.,(pos_ai[2]+pos_aj[2])/2.] #print('%0.5f %0.5f %0.5f' %(MP[0],MP[1],MP[2])) # Print positions #print('%0.5f %0.5f %0.5f' %(pos_ai[0],pos_ai[1],pos_ai[2])) #print('%0.5f %0.5f %0.5f' %(pos_aj[0],pos_aj[1],pos_aj[2])) for spin in ['He','X']: if spin == 'He': offset = 0.000 if spin == 'X': #offset = 0.002 offset = 0.02 if str(bond_type) == 'SINGLE': #print('%s %0.5f %0.5f %0.5f' %(spin,MP[0]+offset,MP[1]+offset,MP[2]+offset)) fods.append(Atom(spin,[MP[0]+offset,MP[1]+offset,MP[2]+offset])) if str(bond_type) == 'DOUBLE': #print('%s %0.5f %0.5f %0.5f' %(spin,MP[0]+offset,MP[1]+offset,MP[2]+0.5+offset)) #print('%s %0.5f %0.5f %0.5f' %(spin,MP[0]+offset,MP[1]+offset,MP[2]-0.5+offset)) fods.append(Atom(spin,[MP[0]+offset,MP[1]+offset,MP[2]+0.5+offset])) fods.append(Atom(spin,[MP[0]+offset,MP[1]+offset,MP[2]-0.5+offset])) if str(bond_type) == 'TRIPLE': #print('%s %0.5f %0.5f %0.5f' %(spin,MP[0]+offset,MP[1]+offset,MP[2]+0.5+offset)) #print('%s %0.5f %0.5f %0.5f' %(spin,MP[0]+offset,MP[1]+offset,MP[2]-0.5+offset)) #print('%s %0.5f %0.5f %0.5f' %(spin,MP[0]-0.5+offset,MP[1]+offset,MP[2]+offset)) fods.append(Atom(spin,[MP[0]+offset,MP[1]+offset,MP[2]+0.5+offset])) fods.append(Atom(spin,[MP[0]+offset,MP[1]+offset,MP[2]-0.5+offset])) fods.append(Atom(spin,[MP[0]-0.5+offset,MP[1]+offset,MP[2]+offset])) w = Chem.SDWriter('%s.sdf' % 'pylewis') w.write(m) w.flush() # sdf2xyz struct = read('%s.sdf' % 'pylewis') struct_fods = Atoms() struct_fods.extend(struct) struct_fods.extend(fods) #print(struct.get_chemical_symbols()) write('%s.xyz' % 'pylewis',struct,'xyz') write('%s_fods.xyz' % 'pylewis',struct_fods,'xyz')
class SelectorTests(unittest.TestCase): def _set_atoms_pos(self, atoms, pos): p = atoms.get_positions() p = p + np.array(pos) atoms.set_positions(p) def _set_molecule_pos(self, atoms, molecule, pos): p = atoms.get_positions() dx = pos[0] - p[molecule[0]][0] dy = pos[1] - p[molecule[0]][1] dz = pos[2] - p[molecule[0]][2] for i in molecule: p[i][0] += dx p[i][1] += dy p[i][2] += dz atoms.set_positions(p) def setUp(self): self._atoms = Atoms() self._mcount = 5 self._edge = 100.0 x = np.linspace(-self._edge/2.0, self._edge/2.0, self._mcount) c = 0 for i in x: for j in x: for k in x: ch4 = molecule("CH4") self._set_atoms_pos(ch4, (i,j,k)) self._atoms.extend(ch4) c += 1 Mixer.set_atom_ids(self._atoms) def test_calcbox_all(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), dim=(self._edge + 5, self._edge + 5, self._edge + 5)) sa, srmap, sw = cb.select_atoms(self._atoms) ra = self._atoms self.assertEqual(ra, sa) def test_calcbox_subset(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), cutoff=0.0, dim=(50.0, 50.0, 50.0)) sa, srmap, sw = cb.select_atoms(self._atoms) correct_ids = set([307, 215, 405, 280, 281, 410, 155, 156, 285, 286, 415, 160, 289, 290, 419, 165, 294, 455, 430, 432, 305, 306, 435, 180, 414, 310, 439, 312, 185, 186, 315, 188, 190, 181, 193, 343, 161, 457, 330, 311, 332, 205, 462, 335, 337, 210, 340, 213, 313, 218, 314, 465, 444, 338, 437, 440, 318, 319, 460]) self.assertEqual(set(Mixer.get_atom_ids(sa)), correct_ids) def test_calcbox_moving_ch4(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), cutoff=2.0, dim=(55.0, 55.0, 55.0), debug=0) ch4 = [0, 1, 2, 3] # these are atoms indexes and ids z = np.linspace(-self._edge/2.0 - 25, self._edge/2.0 + 25, 100) x = np.zeros_like(z) y = np.zeros_like(z) pos = np.column_stack((x, y, z)) for i in range(len(pos)): self._set_molecule_pos(self._atoms, ch4, pos[i]) sa, srmap, sw = cb.select_atoms(self._atoms) s_ids = set(Mixer.get_atom_ids(sa)) all_ids = set(Mixer.get_atom_ids(self._atoms)) inside_ids = s_ids.intersection(set(ch4)) if not (len(inside_ids) == 0 or len(inside_ids) == 4): print("CH4 pos: %s" % pos[i]) print("CH4 in selection: %s" % inside_ids) def test_weights(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), cutoff=2.0, dim=(100.0, 100.0, 100.0), inner_dim=(50.0, 50.0, 50.0)) # test all three axis test_positions = np.column_stack((np.linspace(-55.0, 55.0, 100), np.zeros(100), np.zeros(100))) test_positions = np.append(test_positions, np.column_stack( (np.zeros(100), np.linspace(-55.0, 55.0, 100), np.zeros(100))), axis=0) test_positions = np.append(test_positions, np.column_stack( (np.zeros(100), np.zeros(100), np.linspace(-55.0, 55.0, 100))), axis=0) # and all 8 corners too a = 37.5 test_positions = np.append(test_positions, np.array(( (-a, -a, -a), (-a, -a, a), (-a, a, -a), (-a, a, -a), (a, -a, -a), (a, -a, a), (a, a, -a), (a, a, a))), axis=0) correct_weights = np.loadtxt("weight_test.csv", delimiter=",") for i in range(len(test_positions)): w = cb.get_weight(test_positions[i]) self.assertEqual(correct_weights[i], w)
class SelectorTests(unittest.TestCase): def _set_atoms_pos(self, atoms, pos): p = atoms.get_positions() p = p + np.array(pos) atoms.set_positions(p) def _set_molecule_pos(self, atoms, molecule, pos): p = atoms.get_positions() dx = pos[0] - p[molecule[0]][0] dy = pos[1] - p[molecule[0]][1] dz = pos[2] - p[molecule[0]][2] for i in molecule: p[i][0] += dx p[i][1] += dy p[i][2] += dz atoms.set_positions(p) def setUp(self): self._atoms = Atoms() self._mcount = 5 self._edge = 100.0 x = np.linspace(-self._edge / 2.0, self._edge / 2.0, self._mcount) c = 0 for i in x: for j in x: for k in x: ch4 = molecule("CH4") self._set_atoms_pos(ch4, (i, j, k)) self._atoms.extend(ch4) c += 1 Mixer.set_atom_ids(self._atoms) def test_calcbox_all(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), dim=(self._edge + 5, self._edge + 5, self._edge + 5)) sa, srmap, sw = cb.select_atoms(self._atoms) ra = self._atoms self.assertEqual(ra, sa) def test_calcbox_subset(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), cutoff=0.0, dim=(50.0, 50.0, 50.0)) sa, srmap, sw = cb.select_atoms(self._atoms) correct_ids = set([ 307, 215, 405, 280, 281, 410, 155, 156, 285, 286, 415, 160, 289, 290, 419, 165, 294, 455, 430, 432, 305, 306, 435, 180, 414, 310, 439, 312, 185, 186, 315, 188, 190, 181, 193, 343, 161, 457, 330, 311, 332, 205, 462, 335, 337, 210, 340, 213, 313, 218, 314, 465, 444, 338, 437, 440, 318, 319, 460 ]) self.assertEqual(set(Mixer.get_atom_ids(sa)), correct_ids) def test_calcbox_moving_ch4(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), cutoff=2.0, dim=(55.0, 55.0, 55.0), debug=0) ch4 = [0, 1, 2, 3] # these are atoms indexes and ids z = np.linspace(-self._edge / 2.0 - 25, self._edge / 2.0 + 25, 100) x = np.zeros_like(z) y = np.zeros_like(z) pos = np.column_stack((x, y, z)) for i in range(len(pos)): self._set_molecule_pos(self._atoms, ch4, pos[i]) sa, srmap, sw = cb.select_atoms(self._atoms) s_ids = set(Mixer.get_atom_ids(sa)) all_ids = set(Mixer.get_atom_ids(self._atoms)) inside_ids = s_ids.intersection(set(ch4)) if not (len(inside_ids) == 0 or len(inside_ids) == 4): print("CH4 pos: %s" % pos[i]) print("CH4 in selection: %s" % inside_ids) def test_weights(self): cb = CalcBox(name="testbox", pos=(0., 0., 0.), cutoff=2.0, dim=(100.0, 100.0, 100.0), inner_dim=(50.0, 50.0, 50.0)) # test all three axis test_positions = np.column_stack( (np.linspace(-55.0, 55.0, 100), np.zeros(100), np.zeros(100))) test_positions = np.append(test_positions, np.column_stack( (np.zeros(100), np.linspace(-55.0, 55.0, 100), np.zeros(100))), axis=0) test_positions = np.append(test_positions, np.column_stack( (np.zeros(100), np.zeros(100), np.linspace(-55.0, 55.0, 100))), axis=0) # and all 8 corners too a = 37.5 test_positions = np.append(test_positions, np.array( ((-a, -a, -a), (-a, -a, a), (-a, a, -a), (-a, a, -a), (a, -a, -a), (a, -a, a), (a, a, -a), (a, a, a))), axis=0) correct_weights = np.loadtxt("weight_test.csv", delimiter=",") for i in range(len(test_positions)): w = cb.get_weight(test_positions[i]) self.assertEqual(correct_weights[i], w)