def test_assembly(amine2, aldehyde2, boronic_acid2, diol2): repeat_units = 3 monomer_joins = 2 * repeat_units - 1 p1 = stk.Polymer([amine2, aldehyde2], stk.Linear('AB', [0, 0], repeat_units)) p2 = stk.Polymer([amine2, aldehyde2], stk.Linear('AB', [1, 1], repeat_units, 'fg')) p3 = stk.Polymer([boronic_acid2, diol2], stk.Linear('AB', [0, 0], repeat_units)) path = os.path.join('linear_topology_tests', 'p1.mol') p1.write(path) p2.write(path.replace('1', '2')) p3.write(path.replace('1', '3')) assert p1.bonds_made == monomer_joins assert p2.bonds_made == monomer_joins assert p3.bonds_made == monomer_joins * 2 monomer_atom_count = (amine2.mol.GetNumAtoms() + aldehyde2.mol.GetNumAtoms()) # 3 atoms are lost at each join in p1 and p2 due to condensation. # In p1 an atom is gained due to replacing aldehyde fg with Hs. assert (p1.mol.GetNumAtoms() == monomer_atom_count * repeat_units - 3 * monomer_joins + 1) assert (p2.mol.GetNumAtoms() == monomer_atom_count * repeat_units - 3 * monomer_joins) # p3 loses two atoms because boronic acid OH groups are repalced # with H. monomer_atom_count = (boronic_acid2.mol.GetNumAtoms() + diol2.mol.GetNumAtoms()) assert (p3.mol.GetNumAtoms() == monomer_atom_count * repeat_units - 6 * monomer_joins - 2) assert p1.bb_counter[amine2] == repeat_units assert p1.bb_counter[aldehyde2] == repeat_units assert p2.bb_counter[amine2] == repeat_units assert p2.bb_counter[aldehyde2] == repeat_units assert p3.bb_counter[boronic_acid2] == repeat_units assert p3.bb_counter[diol2] == repeat_units assert p1.topology == stk.Linear('AB', [0, 0], repeat_units) assert p2.topology == stk.Linear('AB', [1, 1], repeat_units, 'fg') assert p3.topology == stk.Linear('AB', [0, 0], repeat_units) assert (p1.mol.GetNumBonds() == amine2.mol.GetNumBonds() * repeat_units + aldehyde2.mol.GetNumBonds() * repeat_units - monomer_joins * 2 + 1) assert (p2.mol.GetNumBonds() == amine2.mol.GetNumBonds() * repeat_units + aldehyde2.mol.GetNumBonds() * repeat_units - monomer_joins * 2) assert (p3.mol.GetNumBonds() == boronic_acid2.mol.GetNumBonds() * repeat_units + diol2.mol.GetNumBonds() * repeat_units - monomer_joins * 4 - 2)
def tmp_polymer_pop(tmp_bromine2, tmp_bromine2_alt1): p1 = stk.Polymer([tmp_bromine2, tmp_bromine2_alt1], stk.Linear('AB', [0, 0], 1), 'p1') p2 = stk.Polymer([tmp_bromine2, tmp_bromine2_alt1], stk.Linear('ABBA', [0, 0], 1), 'p2') p3 = stk.Polymer([tmp_bromine2, tmp_bromine2_alt1], stk.Linear('ABA', [0, 0], 1), 'p3') p4 = stk.Polymer([tmp_bromine2, tmp_bromine2_alt1], stk.Linear('AAB', [0, 0], 1), 'p4') return stk.Population(p1, p2, p3, p4)
def test_caching(amine2, aldehyde2): # Other tests assume that the cache is turned off. Make sure # that this test restores cache to off after it finishes. try: stk.OPTIONS['cache'] = True polymer = stk.Polymer([amine2, aldehyde2], stk.Linear('AB', [0, 0], 3)) polymer2 = stk.Polymer([amine2, aldehyde2], stk.Linear('AB', [0, 0], 3)) assert polymer is polymer2 stk.OPTIONS['cache'] = False polymer3 = stk.Polymer([amine2, aldehyde2], stk.Linear('AB', [1, 0.5], 3)) assert polymer is not polymer3 except Exception: raise finally: stk.OPTIONS['cache'] = False
def generate_polymer(self, permutation, monomers_dict, name): sequence = string.ascii_uppercase[:len(permutation)] isomers = [0 for i in permutation] structunits = [] for id in permutation: smiles = rdkit.MolToSmiles(rdkit.MolFromSmiles(monomers_dict[id]), canonical=True) mol = rdkit.AddHs(rdkit.MolFromSmiles(smiles)) rdkit.AllChem.EmbedMolecule(mol, rdkit.AllChem.ETKDG()) structunits.append(stk.StructUnit2.rdkit_init(mol, "bromine")) repeat = stk.Polymer(structunits, stk.Linear(sequence, isomers, n=1), name=name) polymer = stk.Polymer(structunits, stk.Linear(sequence, isomers, n=self.n_repeat), name=name) rdkit.MolToMolFile(polymer.mol, 'test.mol') return polymer, repeat
def _combine_to_dyes(self, i, smile_tuple): A_smiles = smile_tuple[0] B_smiles = smile_tuple[1] C_smiles = smile_tuple[2] Amol = rdkit.AddHs(rdkit.MolFromSmiles(A_smiles)) Bmol = rdkit.AddHs(rdkit.MolFromSmiles(B_smiles)) Cmol = rdkit.AddHs(rdkit.MolFromSmiles(C_smiles)) A = stk.StructUnit2.rdkit_init(Amol, 'bromine') B = stk.StructUnit2.rdkit_init(Bmol, 'bromine') C = stk.StructUnit2.rdkit_init(Cmol, 'bromine') try: dye1 = stk.Polymer([B, C, B], stk.Linear('ABA', [0,0,1], n=1, ends='fg')) X = stk.StructUnit2.rdkit_init(dye1.mol, 'bromine') dye = stk.Polymer([A, X, A], stk.Linear('ABA', [0,0,1], n=1)) dyemol = dye.mol stk.rdkit_ETKDG(dye) id = '{:08d}'.format(i) except Exception as e: print(e, 'Build error') return A_smiles, B_smiles, C_smiles, dye, id
def tmp_polymer(amine2, aldehyde2): return stk.Polymer([amine2, aldehyde2], stk.Linear('AB', [0, 0], 3), 'tmp_polymer')
def sa_conformers(file_1, func_1, file_2, func_2, units, radius): # turn off cache stk.OPTIONS['cache'] = False # number of conformers N = 10 """ functional groups: ['diol'] and ['dibromine']/['difluorene'] or ['bromine'] and ['bromine']/['iodine'] """ name_1 = file_1.replace('.mol', '') unit_1 = stk.StructUnit2(file_1, func_1) name_2 = file_2.replace('.mol', '') unit_2 = stk.StructUnit2(file_2, func_2) # make polymer NAME = name_1+'_'+name_2+'_AB_poly' print(f'Creating polymer: {NAME}') polymer = stk.Polymer([unit_1, unit_2], stk.Linear('AB', [0, 0], n=units, ends='h')) # write unoptimized structure polymer.write(NAME+'.mol') mol_polymer = rdkit.MolFromMolFile(NAME + '.mol') #print(f'{NAME} has {polymer.mol.get_no_atoms()} atoms!') print(f'Optimizing polymer {NAME} and saving {N} conformers') # clean molecule with ETKDG embedder = stk.UFF(use_cache=False) embedder.optimize(polymer, conformer=-1) # write optimized polymer to json polymer.dump(NAME+'_opt.json') polymer.write(NAME+'_opt.mol') # make N conformers of the polymer molecule etkdg = rdkit.ETKDGv2() etkdg.randomSeed = 1000 etkdg.verbose = True etkdg.maxIterations = 200000 cids = rdkit.EmbedMultipleConfs( mol=polymer.mol, numConfs=N, params=etkdg ) print(f'Made {len(cids)} conformers...') print(f'Warning! I have not implemented an optimization of the ETKDG cleaned polymers!') # iterate over conformers and save structure file_dir = '/home/fanyuzhao/Monomers/OH+F/dimer/conformers/' new_dir = file_dir+NAME+'_'+str(units)+'_'+str(radius)+'/' for cid in cids: # build directories if not os.path.exists(new_dir): os.makedirs(new_dir) # write optimized polymer to mol polymer.write(new_dir+NAME+'_'+str(cid)+'_opt.mol', conformer=cid) # write optimized polymer to pdb polymer.write(new_dir+NAME+'_'+str(cid)+'_opt.pdb', conformer=cid) print(f'Done! {N} ETKDG conformers of polymer written to {NAME}_{N}_opt.mol/pdb') # pdb file from stk can not be read in freesasa # save the new pdb file in rdkit from mol files for item in os.listdir(new_dir): if item.endswith('.mol'): file_pdb = item.replace('.mol', '') a = rdkit.MolFromMolFile(os.path.join(new_dir, item)) # hydrogens are removed when converting the file in rdkit b = rdkit.AddHs(a, addCoords = True) rdkit.MolToPDBFile(b, new_dir + file_pdb + '_new.pdb') # calculate solvent accessible surface area(probe radius = 1.4Å and 3.6Å) # hydrogens are removed in the default option # hetatm are ignored in the default option options_with_Hs = { 'hetatm' : True, 'hydrogen' : True, 'join-models' : False, 'skip-unknown' : False, 'halt-at-unknown' : False } sa_list = [] pdb_list = [] # loop all new pdb files for pdb in os.listdir(new_dir): if pdb.endswith("_new.pdb"): # use freesasa to calculate SASA para = freesasa.Parameters() freesasa.Parameters.setProbeRadius(para, radius) free_struct = freesasa.Structure(os.path.join(new_dir, pdb), options = options_with_Hs) free_calc = freesasa.calc(free_struct, para) total = free_calc.totalArea() # keep 3 decimals decimal = round(total, 4) sa_list.append(decimal) name_pdb = pdb.replace('.pdb', '') pdb_list.append(name_pdb) # calculate average SASA(probe radius = 1.4Å) sa_average = round(sum(sa_list) / len(sa_list), 4) atom_number = mol_polymer.GetNumAtoms() normalized_sa = round(sa_average / atom_number, 4) with open (file_dir + 'Average surface area of conformers.txt', 'a+') as Asa: Asa.write(f'The normalized surface area of {NAME}_{units} is ' + str(normalized_sa) + ' Å^2 with the probe size of ' + str(radius) + f'Å and chain length of {units}.\n') print ('The avarage surface area of the conformers is ' + str(sa_average) + ' Å^2 with the probe size of ' + str(radius) + 'Å.') # save data to a csv table # save pdb file and surface area to a directory dic = {p: s for p, s in zip(pdb_list, sa_list)} download_dict = new_dir + 'Solvent accessible surface area of ' + NAME +'.csv' csv = open(download_dict, 'w') columnTitleRow = "Polymer_name, SASA\n" csv.write(columnTitleRow) for key in dic.keys(): Polymer_name = key SASA = dic[key] row = Polymer_name + "," + str(SASA) + "\n" csv.write(row) print ('Nomalized solvent accessible surface area is '+ str(normalized_sa) + ' Å^2 with the probe size of ' + str(radius) + 'Å.')
def test_phenyl_with_ring_amine(ring_amine): p = stk.Polymer([ring_amine], stk.Linear('A', [1], 8)) p.write(join(test_dir, 'ring_amine_ring_amine.mol'))
def test_boronic_acid_with_diol(boronic_acid2, diol2): p = stk.Polymer([boronic_acid2, diol2], stk.Linear('ABAB', [1, 1, 0, 0], 4)) p.write(join(test_dir, 'boronic_acid_diol.mol'))
def test_diol_with_difluorene(diol2, difluorene2): p = stk.Polymer([diol2, difluorene2], stk.Linear('ABAB', [1, 1, 0, 0], 4)) p.write(join(test_dir, 'diol_difluorene.mol'))
def test_bi_fg_bb(diol2, difluorene_dibromine): p = stk.Polymer([diol2, difluorene_dibromine], stk.Linear('ABAB', [1, 1, 0, 0], 4)) p.write(join(test_dir, 'diol_difluorene_dibromine.mol'))
def poly(file_1, func_1, file_2, func_2, units): # turn off cache stk.OPTIONS['cache'] = False # make polymer name_base = '_diol_difluorene_poly' name_1 = file_1.replace('.mol', '') name_2 = file_2.replace('.mol', '') global NAME NAME = name_1+'_'+name_2+name_base unit_1 = stk.StructUnit2(file_1, func_1) unit_2 = stk.StructUnit2(file_2, func_2) polymer = stk.Polymer([unit_1, unit_2], stk.Linear('AB', [0, 0], n=units, ends='h')) print(f'Creating polymer: {NAME}') polymer.write(NAME+'.mol') mol_polymer = Chem.MolFromMolFile(NAME + '.mol') # optimization print(f'Optimizing {NAME}') macromodel_dir = 'pathMacroModel/' rff = stk.MacroModelForceField( macromodel_path=macromodel_dir, restricted=True ) uff = stk.MacroModelForceField( macromodel_path=macromodel_dir, restricted=False ) md = stk.MacroModelMD( macromodel_path=macromodel_dir, temperature=700, simulation_time=2000, time_step=1, eq_time=100 ) macromodel = stk.OptimizerSequence(rff, uff, md) macromodel.optimize(polymer) print (f'Optimization completed: {NAME}') # save files # make different directories if name_base == '_anhydride_poly': new_dir_1 = file_dir+'Dianhydride/' if not os.path.exists(new_dir_1): os.makedirs(new_dir_1) else: pass polymer.write(new_dir_1+NAME+'.mol') print (f'{NAME} has been saved as dianhydride.') return (new_dir_1+NAME+'.mol') else: new_dir_2 = file_dir+'Polybenzodioxane/' if not os.path.exists(new_dir_2): os.makedirs(new_dir_2) else: pass polymer.write(new_dir_2+NAME+'.mol') print (f'{NAME} has been saved as polybenzodioxane.') return (new_dir_2+NAME+'.mol')
def polymer(amine2, aldehyde2): return stk.Polymer([amine2, aldehyde2], stk.Linear('AB', [0, 0], 1))