{"id":32177589,"url":"https://github.com/drrdom/pmapper","last_synced_at":"2026-02-19T07:03:04.774Z","repository":{"id":37759248,"uuid":"155721995","full_name":"DrrDom/pmapper","owner":"DrrDom","description":"3D pharmacophore signatures and fingerprints","archived":false,"fork":false,"pushed_at":"2025-05-08T11:00:36.000Z","size":859,"stargazers_count":111,"open_issues_count":1,"forks_count":24,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-11-27T19:06:37.927Z","etag":null,"topics":["chemoinformatics","pharmacophore"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DrrDom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-11-01T13:47:39.000Z","updated_at":"2025-11-05T09:33:27.000Z","dependencies_parsed_at":"2022-07-15T21:48:21.767Z","dependency_job_id":"e6047560-82eb-4eb2-8299-3ff95c246f46","html_url":"https://github.com/DrrDom/pmapper","commit_stats":{"total_commits":115,"total_committers":1,"mean_commits":115.0,"dds":0.0,"last_synced_commit":"896c1738ddbe2e1946fa58bc90c7e53dd0bd703f"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/DrrDom/pmapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrrDom%2Fpmapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrrDom%2Fpmapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrrDom%2Fpmapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrrDom%2Fpmapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DrrDom","download_url":"https://codeload.github.com/DrrDom/pmapper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DrrDom%2Fpmapper/sbom","scorecard":{"id":42608,"data":{"date":"2025-08-11","repo":{"name":"github.com/DrrDom/pmapper","commit":"2f77e6482f6bd9bd7cc1f62b5d569ffdb8e8aafd"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 1/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-14T21:54:21.901Z","repository_id":37759248,"created_at":"2025-08-14T21:54:21.901Z","updated_at":"2025-08-14T21:54:21.901Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29605807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T06:47:36.664Z","status":"ssl_error","status_checked_at":"2026-02-19T06:45:47.551Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chemoinformatics","pharmacophore"],"created_at":"2025-10-21T20:13:50.256Z","updated_at":"2026-02-19T07:03:04.769Z","avatar_url":"https://github.com/DrrDom.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pmapper - 3D pharmacophore signatures and fingerprints\n\nPmapper is a Python module to generate 3D pharmacophore signatures and fingerprints.\nSignatures uniquely encode 3D pharmacophores with hashes suitable for fast identification of identical pharmacophores.\n\n## Dependency\n\n`rdkit \u003e= 2017.09`  \n`networkx \u003e= 2`\n\n## Installation\n```text\npip install pmapper\n```\n\n## Examples\n\n### Load modules\n```python\nfrom pmapper.pharmacophore import Pharmacophore as P\nfrom rdkit import Chem\nfrom rdkit.Chem import AllChem\nfrom pprint import pprint\n```\n### Create pharmacophore from a single conformer using default feature definitions\n```python\n# load a molecule from SMILES and generate 3D coordinates\nmol = Chem.MolFromSmiles('C1CC(=O)NC(=O)C1N2C(=O)C3=CC=CC=C3C2=O')  # talidomide\nmol = Chem.AddHs(mol)\nAllChem.EmbedMolecule(mol, randomSeed=42)\n\n# create pharmacophore\np = P()\np.load_from_mol(mol)\n```\n### Get 3D pharmacophore signature\n```python\n# get 3D pharmacophore signature\nsig = p.get_signature_md5()\nprint(sig)\n```\nOutput:\n```text\n98504647beeb143ae50bb6b7798ca0f0\n```\n### Get 3D pharmacophore signature with non-zero tolerance\n```python\nsig = p.get_signature_md5(tol=5)\nprint(sig)\n```\nOutput:\n```text\nbc54806ba01bf59736a7b62b017d6e1d\n```\n### Create pharmacophores for a multiple conformer compound\n```python\nfrom pmapper.utils import load_multi_conf_mol\n\n# create multiple conformer molecule\nAllChem.EmbedMultipleConfs(mol, numConfs=10, randomSeed=1024)\n\nps = load_multi_conf_mol(mol)\n\nsig = [p.get_signature_md5() for p in ps]\n\npprint(sig)  # identical signatures occur\n```\nOutput:\n```text\n['d5f5f9d65e39cb8605f1fa9db5b2fbb0',\n '6204791002d1e343b2bde323149fa780',\n 'abfabd8a4fcf5719ed6bf2c71a60852c',\n 'dfe9f17d30210cb94b8dd7acf77feae9',\n 'abfabd8a4fcf5719ed6bf2c71a60852c',\n 'e739fb5f9985ce0c65a16da41da4a33f',\n '2297ddf0e437b7fc32077f75e3924dcd',\n 'e739fb5f9985ce0c65a16da41da4a33f',\n '182a00bd9057abd0c455947d9cfa457c',\n '68f226d474808e60ab1256245f64c2b7']\n```\nIdentical hashes should correspond to pharmacophores with low RMSD. Pharmacophores #2 and #4 have identical hash `abfabd8a4fcf5719ed6bf2c71a60852c`. Let's check RMSD.\n```python\nfrom pmapper.utils import get_rms\nfor i in range(len(ps)):\n    print(\"rmsd bewteen 2 and %i pharmacophore:\" % i, round(get_rms(ps[2], ps[i]), 2))\n```\nOutput\n```text\nrmsd bewteen 2 and 0 pharmacophore: 0.63\nrmsd bewteen 2 and 1 pharmacophore: 0.99\nrmsd bewteen 2 and 2 pharmacophore: 0.0\nrmsd bewteen 2 and 3 pharmacophore: 0.41\nrmsd bewteen 2 and 4 pharmacophore: 0.18\nrmsd bewteen 2 and 5 pharmacophore: 0.19\nrmsd bewteen 2 and 6 pharmacophore: 1.15\nrmsd bewteen 2 and 7 pharmacophore: 0.32\nrmsd bewteen 2 and 8 pharmacophore: 0.69\nrmsd bewteen 2 and 9 pharmacophore: 0.36\n```\nThey really have RMSD \u003c binning step (1A by default). However, other pharmacophores with distinct hashes also have low RMSD to #2. Identical hashes guarantee low RMSD between corresponding pharmacophores, but not vice versa.\n\n### Pharmacophore match\nCreate a two-point pharmacophore model and match with a pharmacophore of a molecule (both pharmacophores should have identical binning steps)\n```python\nq = P()\nq.load_from_feature_coords([('a', (3.17, -0.23, 0.24)), ('D', (-2.51, -1.28, -1.14))])\np.fit_model(q)\n```\nOutput\n```text\n(0, 1)\n```\nIf they do not match `None` will be returned\n\n### Generate 3D pharmacophore fingerprint\n```python\n# generate 3D pharmacophore fingerprint which takes into account stereoconfiguration\nb = p.get_fp(min_features=4, max_features=4)   # set of activated bits\nprint(b)\n```\nOutput (a set of activated bit numbers):\n```text\n{259, 1671, 521, 143, 912, 402, 278, 406, 1562, 1692, 1835, 173, 558, 1070, 942, 1202, 1845, 823, 1476, 197, 968, 1355, 845, 1741, 1364, 87, 1881, 987, 1515, 378, 628, 1141, 1401, 1146, 2043}\n```\nChange settings:\n```python\nb = p.get_fp(min_features=4, max_features=4, nbits=4096, activate_bits=2)\nprint(b)\n```\nOutput (a set of activated bit numbers):\n```text\n{389, 518, 2821, 1416, 2952, 395, 3339, 511, 3342, 1937, 1042, 2710, 1817, 1690, 3482, 3737, 286, 1824, 1700, 804, 1318, 2729, 3114, 812, 556, 175, 3763, 2356, 3124, 1077, 1975, 3384, 1081, 185, 65, 1223, 713, 1356, 1998, 1487, 2131, 85, 3670, 1877, 3030, 2395, 1116, 2141, 1885, 347, 2404, 1382, 1257, 3049, 2795, 3691, 2541, 1646, 2283, 241, 113, 3698, 756, 2548, 4086, 2293, 1528, 2802, 127}\n```\n### Save/load pharmacophore\n```python\np.save_to_pma('filename.pma')\n```\nOutput is a text file having json format.\n```python\np = P()\np.load_from_pma('filename.pma')\n```\n### Support other formats\nPharmacophores can be saved/loaded from LigandScout pml-files. Also pharmacophores can be read from xyz-files.\n\n### Caching\nPharmacophores can be created with enabled `cached` argument. This will speed up all futher repeated calls to retrive hash, fingerprints or descriptors.\n```python\np = P(cached=True)\n```\n\n## Speed tests\nGeneration of pharmacophore signatures (hashes) is a CPU-bound task. The computation speed depends on the number of features in pharmacophores.  \nTests were run on a random subset of compounds from Drugbank. Up to 50 conformers were generated for each compound.   \nLaptop configuration:\n- Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz\n- 12 GB RAM\n- calculation was run in 1 thread (the module is thread safe and calculations can be parallelized)\n\nTo run the speed test use `pmapper_speed_test` command line tool\n\n```text\n========== Reading of conformers of molecules ==========\n329 molecules were read in 0.0134 s\n\n========== Creation of pharmacophores (with enabled caching) ==========\n1938 pharmacophores were created in 3.17065 s\n\n========== First calculation of hashes ==========\n2 pharmacophores with 0 features - 0.00014s or 7e-05s per pharmacophore\n2 pharmacophores with 1 features - 0.0001s or 5e-05s per pharmacophore\n12 pharmacophores with 2 features - 0.00042s or 3e-05s per pharmacophore\n44 pharmacophores with 3 features - 0.00212s or 5e-05s per pharmacophore\n100 pharmacophores with 4 features - 0.00933s or 9e-05s per pharmacophore\n103 pharmacophores with 5 features - 0.05155s or 0.0005s per pharmacophore\n105 pharmacophores with 6 features - 0.10857s or 0.00103s per pharmacophore\n109 pharmacophores with 7 features - 0.25322s or 0.00232s per pharmacophore\n117 pharmacophores with 8 features - 0.59508s or 0.00509s per pharmacophore\n101 pharmacophores with 9 features - 0.8795s or 0.00871s per pharmacophore\n105 pharmacophores with 10 features - 1.61349s or 0.01537s per pharmacophore\n100 pharmacophores with 11 features - 2.24937s or 0.02249s per pharmacophore\n103 pharmacophores with 12 features - 3.53308s or 0.0343s per pharmacophore\n117 pharmacophores with 13 features - 6.49837s or 0.05554s per pharmacophore\n103 pharmacophores with 14 features - 7.54796s or 0.07328s per pharmacophore\n142 pharmacophores with 15 features - 14.92654s or 0.10512s per pharmacophore\n104 pharmacophores with 16 features - 13.86378s or 0.13331s per pharmacophore\n100 pharmacophores with 17 features - 17.94023s or 0.1794s per pharmacophore\n120 pharmacophores with 18 features - 28.01455s or 0.23345s per pharmacophore\n136 pharmacophores with 19 features - 42.53481s or 0.31276s per pharmacophore\n113 pharmacophores with 20 features - 45.88228s or 0.40604s per pharmacophore\n\n========== Second calculation of hashes of the same pharmacophores ==========\n2 pharmacophores with 0 features - 5e-05s or 2e-05s per pharmacophore\n2 pharmacophores with 1 features - 3e-05s or 1e-05s per pharmacophore\n12 pharmacophores with 2 features - 0.00012s or 1e-05s per pharmacophore\n44 pharmacophores with 3 features - 0.00041s or 1e-05s per pharmacophore\n100 pharmacophores with 4 features - 0.00089s or 1e-05s per pharmacophore\n103 pharmacophores with 5 features - 0.00166s or 2e-05s per pharmacophore\n105 pharmacophores with 6 features - 0.00316s or 3e-05s per pharmacophore\n109 pharmacophores with 7 features - 0.00707s or 6e-05s per pharmacophore\n117 pharmacophores with 8 features - 0.0166s or 0.00014s per pharmacophore\n101 pharmacophores with 9 features - 0.02005s or 0.0002s per pharmacophore\n105 pharmacophores with 10 features - 0.03527s or 0.00034s per pharmacophore\n100 pharmacophores with 11 features - 0.05271s or 0.00053s per pharmacophore\n103 pharmacophores with 12 features - 0.08097s or 0.00079s per pharmacophore\n117 pharmacophores with 13 features - 0.13274s or 0.00113s per pharmacophore\n103 pharmacophores with 14 features - 0.1588s or 0.00154s per pharmacophore\n142 pharmacophores with 15 features - 0.32687s or 0.0023s per pharmacophore\n104 pharmacophores with 16 features - 0.29255s or 0.00281s per pharmacophore\n100 pharmacophores with 17 features - 0.38286s or 0.00383s per pharmacophore\n120 pharmacophores with 18 features - 0.61327s or 0.00511s per pharmacophore\n136 pharmacophores with 19 features - 0.93486s or 0.00687s per pharmacophore\n113 pharmacophores with 20 features - 0.94041s or 0.00832s per pharmacophore\n```\n\n## Documentation\nMore documentation can be found here - https://pmapper.readthedocs.io/en/latest/\n\n## Changelog\n**1.0.0**\n- added functionality to calculate 3D pharmacophore descriptors for molecules with exclusion of single atoms (for the purpose of model interpretation)\n- added convenience function get_feature_ids\n- added function add_feature to manually edit/construct a pharmacophore\n- added save/load of pharmit pharmacophore models\n\n\n- IMPORTANT: changed the hashing procedure to make it more stable (pickle dependency was removed). This breaks compatibility with previously generated md5 hashes with `get_signature_md5`, `iterate_pharm` and `iterate_pharm1` functions, all other functionality was not affected. \n\n**1.0.1**\n- `fit_model` function can return rms by request\n\n**1.0.2**\n- `fit_model` function now returns a dict of mapped feature ids\n\n**1.0.3**\n- add `get_subpharmacophore` function\n- fix `get_mirror_pharmacophore` function to use the same bin step and cached args as for the source pharmacophore instance  \n\n**1.0.4**\n- fix installation of dependency `networkx`\n- add citations on examples of `pmapper` descriptors used for machine learning\n\n**1.1**\n- change SMARTS pattern to avoid matching positively charge nitrogen atoms as H-bond acceptors\n\n**1.1.1**\n- fix missing aromatic features when reading LigandScout models\n\n**1.1.2**\n- add treatment of exclusion volume features in LigandScout files\n\n**1.1.3**\n- add file format check for loading of xyz file\n\n## Citation\nLigand-Based Pharmacophore Modeling Using Novel 3D Pharmacophore Signatures  \nAlina Kutlushina, Aigul Khakimova, Timur Madzhidov, Pavel Polishchuk  \n*Molecules* **2018**, 23(12), 3094  \nhttps://doi.org/10.3390/molecules23123094\n\n##### Further publications\n\n###### MD pharmacophores\nVirtual Screening Using Pharmacophore Models Retrieved from Molecular Dynamic Simulations  \nPavel Polishchuk, Alina Kutlushina, Dayana Bashirova, Olena Mokshyna, Timur Madzhidov  \n*Int. J. Mol. Sci.* **2019**, 20(23), 5834  \nhttps://doi.org/10.3390/ijms20235834\n\n###### Pmapper descriptors in machine learning\nQSAR Modeling Based on Conformation Ensembles Using a Multi-Instance Learning Approach  \nZankov, D. V.; Matveieva, M.; Nikonenko, A. V.; Nugmanov, R. I.; Baskin, I. I.; Varnek, A.; Polishchuk, P.; Madzhidov, T. I.  \n*J. Chem. Inf. Model.* **2021**, 61 (10), 4913-4923\nhttps://doi.org/10.1021/acs.jcim.1c00692  \n  \nMulti-Instance Learning Approach to the Modeling of Enantioselectivity of Conformationally Flexible Organic Catalysts  \nZankov, D.; Madzhidov, T.; Polishchuk, P.; Sidorov, P.; Varnek, A.  \n*J. Chem. Inf. Model.* **2023**, 63 (21), 6629-6641  \nhttps://doi.org/10.1021/acs.jcim.3c00393  \n\n\n## License\nBSD-3 clause\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrrdom%2Fpmapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrrdom%2Fpmapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrrdom%2Fpmapper/lists"}