Package: crem
CReM - chemically reasonable mutationsCReMis an open-source Python framework to generate chemical structures using a fragment-based approach.The main idea behind is similar to matched molecular pairs considering context that fragments in the identical context are interchangeable. Therefore, one can create a database of interchangeable fragments and use it for generation of chemically valid structures.Features:Generation of a custom fragment databaseThree modes of structure generation: MUTATE, GROW, LINKContext radius to consider for replacementFragment size to replace and the size of a replacing fragmentProtection of atoms from modification (e.g. scaffold protection)Replacements with fragments occurred in a fragment database with certain minimal frequencyMake randomly chosen replacements up to the specified numberLimitations and known issuesNew ring systems cannot be constructed from fragments, thus representativeness of ring systems in generated structures depends on a used fragment database. We are working on that issue.Very large molecules will not be processed by CReM. If a molecule has more than 30 non-ring single bonds it will not be MUTATED. If a molecule has more than 100 hydrogen atoms it will not be processed by GROW and LINK.Canonicalisation of contexts depends on RDKit SMILES representation. Thus, changing in RDKit SMILES representation may affect fragment databases and make impossible to use a database prepared with previous RDKit version from code running under later RDKit versions.Documentationhttps://crem.readthedocs.io/en/latest/Web appTo play with a tool online.https://crem.imtm.cz/InstallationSeveral command line utilities will be installed to create fragment databases andcremmodule will become available in Python imports to generate structures.From pypi packagepip install cremManually from repositorygit clone https://github.com/DrrDom/crem
cd crem
python3 setup.py sdist bdist_wheel
pip install dist/crem-0.1-py3-none-any.whlUninstallpip uninstall cremDependenciescremrequiresrdkit>=2017.09. To run the guacamol testguacamolshould be installed.Generation of a fragment databaseThis step is required if you want to generate a custom fragment database. You can download precompiled databases obtained by fragmentation of the whole ChEMBL by links provided on this page -http://www.qsar4u.com/pages/crem.php.For convenience there is the bash script crem_create_frag_db.sh which includes all steps below. It takes three positional arguments: input file with SMILES, output directory where intermediate files and a final database will be stored and number of CPUs to use (this is optional, default value is 1).crem_create_frag_db.sh input.smi fragdb_dir 32Fragmentation of input structures:fragmentation -i input.smi -o frags.txt -c 32 -vConvert fragments to standardized representation of a core and a context of a given radius:frag_to_env -i frags.txt -o r3.txt -r 3 -c 32 -vRemove duplicated lines in the output file and count frequency of occurrence of fragemnt-context pairs. These (sortanduniq) arebashutilities but since Win10 is Linux-friendly that should not be a big issue for Win users to execute themsort r3.txt | uniq -c > r3_c.txtCreate DB and import the file to a database tableenv_to_db -i r3_c.txt -o fragments.db -r 3 -c -vLast three steps should be executed for each radius. All tables can be stored in the same database.Structure generationImport necessary functions from the main modulefromcrem.cremimportmutate_mol,grow_mol,link_molsfromrdkitimportChemCreate a molecute andmutateit. Only one heavy atom will be substituted. Default radius is 3.m=Chem.MolFromSmiles('c1cc(OC)ccc1C')# methoxytoluenemols=list(mutate_mol(m,db_name='replacements.db',max_size=1))output example['CCc1ccc(C)cc1',
 'CC#Cc1ccc(C)cc1',
 'C=C(C)c1ccc(C)cc1',
 'CCCc1ccc(C)cc1',
 'CC=Cc1ccc(C)cc1',
 'CCCCc1ccc(C)cc1',
 'CCCOc1ccc(C)cc1',
 'CNCCc1ccc(C)cc1',
 'COCCc1ccc(C)cc1',
 ...
 'Cc1ccc(C(C)(C)C)cc1']Add hydrogens to the molecule tomutate hydrogensas wellmols=list(mutate_mol(Chem.AddHs(m),db_name='replacements.db',max_size=1))output['CCc1ccc(C)cc1',
 'CC#Cc1ccc(C)cc1',
 'C=C(C)c1ccc(C)cc1',
 'CCCc1ccc(C)cc1',
 'Cc1ccc(C(C)C)cc1',
 'CC=Cc1ccc(C)cc1',
 ...
 'COc1ccc(C)cc1C',
 'C=Cc1cc(C)ccc1OC',
 'COc1ccc(C)cc1Cl',
 'COc1ccc(C)cc1CCl']Growmolecule. Only hydrogens will be replaced. Hydrogens should not be added explicitly.mols=list(grow_mol(m,db_name='replacements.db'))output['COc1ccc(C)c(Br)c1',
 'COc1ccc(C)c(C)c1',
 'COc1ccc(C)c(Cl)c1',
 'COc1ccc(C)c(OC)c1',
 'COc1ccc(C)c(N)c1',
 ...
 'COc1ccc(CCN)cc1']Create the second molecule andlinkit to toluenem2=Chem.MolFromSmiles('NCC(=O)O')# glycinemols=list(link_mols(m,m2,db_name='replacements.db'))output['Cc1ccc(OCC(=O)NCC(=O)O)cc1',
 'Cc1ccc(OCCOC(=O)CN)cc1',
 'COc1ccc(CC(=N)NCC(=O)O)cc1',
 'COc1ccc(CC(=O)NCC(=O)O)cc1',
 'COc1ccc(CC(=S)NCC(=O)O)cc1',
 'COc1ccc(CCOC(=O)CN)cc1']You can vary the size of a linker and specify the distance between two attachment points in a linking fragment. There are many other arguments available in these functions, look at theirdocstringsfor details.Additional filters to control fragments chosen for replacingAn example of a filtering function which will keep only fragments containing a specific atom to be chosen for replacing.fromcollectionsimportdefaultdictfromfunctoolsimportpartialfromrdkitimportChemdeffilter_function(row_ids,cur,radius,atom_number):"""The first three arguments should be always the same as shown in the example. These parameters will be passed to a function from a main function, e.g. from mutate_mol. All other arguments are user-defined. The function should return the list of row ids of fragments which will be used for replacing.:param row_id: a list of row ids from CReM database of those fragments which satisfy other selection criteria:param cur: cursor of CReM database:param radius: radius of a context:param atom_number: an atomic number, fragments with this number will be discarded:return list of remaining row ids"""# this part may be kept intact, it collects from DB SMILES of fragments with given row ids# since fragments may occur multiple times (due to different contexts) the results are collected in a dictifnotrow_ids:return[]batch_size=32000# SQLite has a limit on a number of passed values to a queryrow_ids=list(row_ids)smis=defaultdict(list)# {smi_1: [rowid_1, rowid_5, ...], ...}forstartinrange(0,len(row_ids),batch_size):batch=row_ids[start:start+batch_size]sql=f"SELECT rowid, core_smi FROM radius{radius}WHERE rowid IN ({','.join('?'*len(batch))})"fori,smiincur.execute(sql,batch).fetchall():smis[smi].append(i)output_row_ids=[]forsmi,idsinsmis.items():forainChem.MolFromSmiles(smi).GetAtoms():ifa.GetAtomicNum()==atom_number:output_row_ids.extend(ids)returnoutput_row_ids# only F-containing fragments will be chosen for replacingmol=Chem.MolFromSmiles('c1ccccc1C')mols=mutate_mol(mol,db_name='replacements.db',filter_func=partial(filter_function,atom_number=9),max_size=1,max_inc=3)output['Fc1ccccc1', 
 'FC(F)(F)c1ccccc1',
 'FC(F)Oc1ccccc1',
 'FC(F)Sc1ccccc1']MultiprocessingAll functions have an argumentncoresand can make mupltile replacement in one molecule in parallel. If you want to process several molecules in parallel you have to write your own code. However, the described functions are generators and cannot be used withmultiprocessingmodule. Therefore, three complementary functionsmutate_mol2,grow_mol2andlink_mols2were created. They return the list with results and can be pickled and used withmultiprocessing.Poolor other tools.Example:frommultiprocessingimportPoolfromfunctoolsimportpartialfromcrem.cremimportmutate_mol2fromrdkitimportChemp=Pool(2)input_smi=['c1ccccc1N','NCC(=O)OC','NCCCO']input_mols=[Chem.MolFromSmiles(s)forsininput_smi]res=list(p.imap(partial(mutate_mol2,db_name='replacements.db',max_size=1),input_mols))reswould be a list of lists with SMILES of generated moleculesBechmarksGuacamoltaskSMILES LSTM*SMILES GA*Graph GA*Graph MCTS*CReMCelecoxib rediscovery1.0000.7321.0000.3551.000Troglitazone rediscovery1.0000.5151.0000.3111.000Thiothixene rediscovery1.0000.5981.0000.3111.000Aripiprazole similarity1.0000.8341.0000.3801.000Albuterol similarity1.0000.9071.0000.7491.000Mestranol similarity1.0000.791.0000.4021.000C11H240.9930.8290.9710.4100.966C9H10N2O2PF2Cl0.8790.8890.9820.6310.940Median molecules 10.4380.3340.4060.2250.371Median molecules 20.4220.380.4320.1700.434Osimertinib MPO0.9070.8860.9530.7840.995Fexofenadine MPO0.9590.9310.9980.6951.000Ranolazine MPO0.8550.8810.920.6160.969Perindopril MPO0.8080.6610.7920.3850.815Amlodipine MPO0.8940.7220.8940.5330.902Sitagliptin MPO0.5450.6890.8910.4580.763Zaleplon MPO0.6690.4130.7540.4880.770Valsartan SMARTS0.9780.5520.9900.040.994Deco Hop0.9960.9701.0000.5901.000Scaffold Hop0.9980.8851.0000.4781.000total score17.34114.39817.9839.01117.919LicenseBSD-3CitationCReM: chemically reasonable mutations framework for structure generationPavel PolishchukJournal of Cheminformatics2020, 12, (1), 28https://doi.org/10.1186/s13321-020-00431-wControl of Synthetic Feasibility of Compounds Generated with CReMPavel PolishchukJournal of Chemical Information and Modeling2020, 60, 6074-6080https://dx.doi.org/10.1021/acs.jcim.0c00792