From e2bb77a1782ba4b51da06a0ddeb12505b734efba Mon Sep 17 00:00:00 2001 From: FNTwin Date: Mon, 22 Jul 2024 08:32:01 -0600 Subject: [PATCH] merge icml_push into main --squash --- .github/workflows/test.yml | 8 +- .gitignore | 3 + LICENSE | 352 +++++++++++++++ docs/API/available_datasets.md | 3 - docs/API/basedataset.md | 1 + docs/API/datasets/alchemy.md | 1 + docs/API/datasets/ani.md | 1 + docs/API/datasets/comp6.md | 1 + docs/API/datasets/des.md | 1 + docs/API/datasets/gdml.md | 1 + docs/API/datasets/geom.md | 1 + docs/API/datasets/iso_17.md | 1 + docs/API/datasets/l7.md | 1 + docs/API/datasets/md22.md | 1 + docs/API/datasets/metcalf.md | 1 + docs/API/datasets/molecule3d.md | 1 + docs/API/datasets/multixcqm9.md | 1 + docs/API/datasets/nabladft.md | 1 + docs/API/datasets/orbnet_denali.md | 1 + docs/API/datasets/pcqm.md | 1 + docs/API/datasets/proteinfragments.md | 1 + docs/API/datasets/qm1b.md | 1 + docs/API/datasets/qm7x.md | 1 + docs/API/datasets/qmugs.md | 1 + docs/API/datasets/qmx.md | 1 + docs/API/datasets/revmd17.md | 1 + docs/API/datasets/sn2_rxn.md | 1 + docs/API/datasets/solvated_peptides.md | 1 + docs/API/datasets/spice.md | 2 + docs/API/datasets/splinter.md | 1 + docs/API/datasets/tmqm.md | 1 + docs/API/datasets/transition1x.md | 1 + docs/API/datasets/vqm24.md | 1 + docs/API/datasets/waterclusters.md | 1 + docs/API/datasets/waterclusters3_30.md | 1 + docs/API/datasets/x40.md | 1 + docs/API/formats.md | 1 + docs/API/methods.md | 6 +- docs/API/regressor.md | 1 + docs/API/units.md | 3 + docs/API/utils.md | 1 + docs/_overrides/main.html | 46 -- docs/assets/StorageView.png | Bin 0 -> 111109 bytes docs/assets/qdc_logo.png | Bin 0 -> 256743 bytes docs/cli.md | 113 +++++ docs/contribute.md | 59 +++ docs/css/custom-openqdc.css | 92 ++++ docs/data_storage.md | 33 ++ docs/dataset_upload.md | 69 +++ docs/index.md | 69 ++- docs/licensing.md | 3 + docs/normalization_e0s.md | 38 ++ docs/usage.md | 42 ++ env.yml | 6 + mkdocs.yml | 87 +++- openqdc/__init__.py | 17 +- openqdc/cli.py | 214 +++++++++- openqdc/datasets/base.py | 354 +++++++++------ openqdc/datasets/interaction/des.py | 89 ++-- openqdc/datasets/interaction/l7.py | 21 +- openqdc/datasets/interaction/metcalf.py | 27 +- openqdc/datasets/interaction/splinter.py | 17 +- openqdc/datasets/interaction/x40.py | 25 +- openqdc/datasets/io.py | 65 ++- openqdc/datasets/potential/__init__.py | 16 +- openqdc/datasets/potential/alchemy.py | 95 +++++ openqdc/datasets/potential/ani.py | 165 +++---- openqdc/datasets/potential/comp6.py | 36 +- openqdc/datasets/potential/gdml.py | 31 +- openqdc/datasets/potential/geom.py | 13 +- openqdc/datasets/potential/iso_17.py | 17 +- openqdc/datasets/potential/md22.py | 16 + openqdc/datasets/potential/molecule3d.py | 11 +- openqdc/datasets/potential/multixcqm9.py | 17 +- openqdc/datasets/potential/nabladft.py | 19 +- openqdc/datasets/potential/orbnet_denali.py | 23 +- openqdc/datasets/potential/pcqm.py | 41 ++ .../datasets/potential/proteinfragments.py | 192 +++++++++ openqdc/datasets/potential/qm1b.py | 17 +- openqdc/datasets/potential/qm7x.py | 33 +- openqdc/datasets/potential/qmugs.py | 20 +- openqdc/datasets/potential/qmx.py | 402 ++++++++++++++++++ openqdc/datasets/potential/revmd17.py | 26 +- openqdc/datasets/potential/sn2_rxn.py | 14 +- .../datasets/potential/solvated_peptides.py | 12 +- openqdc/datasets/potential/spice.py | 40 +- openqdc/datasets/potential/tmqm.py | 12 +- openqdc/datasets/potential/transition1x.py | 10 +- openqdc/datasets/potential/vqm24.py | 82 ++++ openqdc/datasets/potential/waterclusters.py | 175 ++++++++ .../datasets/potential/waterclusters3_30.py | 8 +- openqdc/datasets/statistics.py | 61 ++- openqdc/datasets/structure.py | 276 ++++++++++++ openqdc/methods/atom_energies.py | 16 +- openqdc/utils/download_api.py | 34 +- openqdc/utils/io.py | 30 +- openqdc/utils/package_utils.py | 1 + openqdc/utils/preprocess.py | 38 -- openqdc/utils/regressor.py | 127 ++++-- openqdc/utils/units.py | 82 ++-- pyproject.toml | 5 +- pytest.ini | 8 + tests/test_download.py | 15 + 103 files changed, 3460 insertions(+), 673 deletions(-) create mode 100644 LICENSE delete mode 100644 docs/API/available_datasets.md create mode 100644 docs/API/basedataset.md create mode 100644 docs/API/datasets/alchemy.md create mode 100644 docs/API/datasets/ani.md create mode 100644 docs/API/datasets/comp6.md create mode 100644 docs/API/datasets/des.md create mode 100644 docs/API/datasets/gdml.md create mode 100644 docs/API/datasets/geom.md create mode 100644 docs/API/datasets/iso_17.md create mode 100644 docs/API/datasets/l7.md create mode 100644 docs/API/datasets/md22.md create mode 100644 docs/API/datasets/metcalf.md create mode 100644 docs/API/datasets/molecule3d.md create mode 100644 docs/API/datasets/multixcqm9.md create mode 100644 docs/API/datasets/nabladft.md create mode 100644 docs/API/datasets/orbnet_denali.md create mode 100644 docs/API/datasets/pcqm.md create mode 100644 docs/API/datasets/proteinfragments.md create mode 100644 docs/API/datasets/qm1b.md create mode 100644 docs/API/datasets/qm7x.md create mode 100644 docs/API/datasets/qmugs.md create mode 100644 docs/API/datasets/qmx.md create mode 100644 docs/API/datasets/revmd17.md create mode 100644 docs/API/datasets/sn2_rxn.md create mode 100644 docs/API/datasets/solvated_peptides.md create mode 100644 docs/API/datasets/spice.md create mode 100644 docs/API/datasets/splinter.md create mode 100644 docs/API/datasets/tmqm.md create mode 100644 docs/API/datasets/transition1x.md create mode 100644 docs/API/datasets/vqm24.md create mode 100644 docs/API/datasets/waterclusters.md create mode 100644 docs/API/datasets/waterclusters3_30.md create mode 100644 docs/API/datasets/x40.md create mode 100644 docs/API/formats.md create mode 100644 docs/API/regressor.md create mode 100644 docs/API/units.md create mode 100644 docs/API/utils.md delete mode 100644 docs/_overrides/main.html create mode 100644 docs/assets/StorageView.png create mode 100644 docs/assets/qdc_logo.png create mode 100644 docs/cli.md create mode 100644 docs/contribute.md create mode 100644 docs/css/custom-openqdc.css create mode 100644 docs/data_storage.md create mode 100644 docs/dataset_upload.md create mode 100644 docs/licensing.md create mode 100644 docs/normalization_e0s.md create mode 100644 docs/usage.md create mode 100644 openqdc/datasets/potential/alchemy.py create mode 100644 openqdc/datasets/potential/proteinfragments.py create mode 100644 openqdc/datasets/potential/qmx.py create mode 100644 openqdc/datasets/potential/vqm24.py create mode 100644 openqdc/datasets/potential/waterclusters.py create mode 100644 openqdc/datasets/structure.py delete mode 100644 openqdc/utils/preprocess.py create mode 100644 pytest.ini create mode 100644 tests/test_download.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9194d2ce..1abf329f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,8 +16,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] - os: ["ubuntu-latest"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + os: ["ubuntu-latest", "macos-latest"] #,"windows-latest" runs-on: ${{ matrix.os }} timeout-minutes: 30 @@ -53,5 +53,5 @@ jobs: - name: Run tests run: python -m pytest - #- name: Test building the doc - # run: mkdocs build + - name: Test building the doc + run: mkdocs build diff --git a/.gitignore b/.gitignore index 7a6dd93f..ffd7edf6 100644 --- a/.gitignore +++ b/.gitignore @@ -149,3 +149,6 @@ cookie.txt *.txt *.sh .DS_Store +*.zarr/ +scripts/ +notebooks/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..94a3b7e2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,352 @@ +Creative Commons Attribution-NonCommercial 4.0 International + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright and +certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + +- Considerations for licensors: Our public licenses are intended for + use by those authorized to give the public permission to use + material in ways otherwise restricted by copyright and certain other + rights. Our licenses are irrevocable. Licensors should read and + understand the terms and conditions of the license they choose + before applying it. Licensors should also secure all rights + necessary before applying our licenses so that the public can reuse + the material as expected. Licensors should clearly mark any material + not subject to the license. This includes other CC-licensed + material, or material used under an exception or limitation to + copyright. More considerations for licensors : + wiki.creativecommons.org/Considerations\_for\_licensors + +- Considerations for the public: By using one of our public licenses, + a licensor grants the public permission to use the licensed material + under specified terms and conditions. If the licensor's permission + is not necessary for any reason–for example, because of any + applicable exception or limitation to copyright–then that use is not + regulated by the license. Our licenses grant only permissions under + copyright and certain other rights that a licensor has authority to + grant. Use of the licensed material may still be restricted for + other reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, such + as asking that all changes be marked or described. Although not + required by our licenses, you are encouraged to respect those + requests where reasonable. More considerations for the public : + wiki.creativecommons.org/Considerations\_for\_licensees + +Creative Commons Attribution-NonCommercial 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and conditions. + +- Section 1 – Definitions. + + - a. Adapted Material means material subject to Copyright and + Similar Rights that is derived from or based upon the Licensed + Material and in which the Licensed Material is translated, + altered, arranged, transformed, or otherwise modified in a + manner requiring permission under the Copyright and Similar + Rights held by the Licensor. For purposes of this Public + License, where the Licensed Material is a musical work, + performance, or sound recording, Adapted Material is always + produced where the Licensed Material is synched in timed + relation with a moving image. + - b. Adapter's License means the license You apply to Your + Copyright and Similar Rights in Your contributions to Adapted + Material in accordance with the terms and conditions of this + Public License. + - c. Copyright and Similar Rights means copyright and/or similar + rights closely related to copyright including, without + limitation, performance, broadcast, sound recording, and Sui + Generis Database Rights, without regard to how the rights are + labeled or categorized. For purposes of this Public License, the + rights specified in Section 2(b)(1)-(2) are not Copyright and + Similar Rights. + - d. Effective Technological Measures means those measures that, + in the absence of proper authority, may not be circumvented + under laws fulfilling obligations under Article 11 of the WIPO + Copyright Treaty adopted on December 20, 1996, and/or similar + international agreements. + - e. Exceptions and Limitations means fair use, fair dealing, + and/or any other exception or limitation to Copyright and + Similar Rights that applies to Your use of the Licensed + Material. + - f. Licensed Material means the artistic or literary work, + database, or other material to which the Licensor applied this + Public License. + - g. Licensed Rights means the rights granted to You subject to + the terms and conditions of this Public License, which are + limited to all Copyright and Similar Rights that apply to Your + use of the Licensed Material and that the Licensor has authority + to license. + - h. Licensor means the individual(s) or entity(ies) granting + rights under this Public License. + - i. NonCommercial means not primarily intended for or directed + towards commercial advantage or monetary compensation. For + purposes of this Public License, the exchange of the Licensed + Material for other material subject to Copyright and Similar + Rights by digital file-sharing or similar means is NonCommercial + provided there is no payment of monetary compensation in + connection with the exchange. + - j. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, + distribution, dissemination, communication, or importation, and + to make material available to the public including in ways that + members of the public may access the material from a place and + at a time individually chosen by them. + - k. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and + of the Council of 11 March 1996 on the legal protection of + databases, as amended and/or succeeded, as well as other + essentially equivalent rights anywhere in the world. + - l. You means the individual or entity exercising the Licensed + Rights under this Public License. Your has a corresponding + meaning. + +- Section 2 – Scope. + + - a. License grant. + - 1. Subject to the terms and conditions of this Public + License, the Licensor hereby grants You a worldwide, + royalty-free, non-sublicensable, non-exclusive, irrevocable + license to exercise the Licensed Rights in the Licensed + Material to: + - A. reproduce and Share the Licensed Material, in whole + or in part, for NonCommercial purposes only; and + - B. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + - 2. Exceptions and Limitations. For the avoidance of doubt, + where Exceptions and Limitations apply to Your use, this + Public License does not apply, and You do not need to comply + with its terms and conditions. + - 3. Term. The term of this Public License is specified in + Section 6(a). + - 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter + created, and to make technical modifications necessary to do + so. The Licensor waives and/or agrees not to assert any + right or authority to forbid You from making technical + modifications necessary to exercise the Licensed Rights, + including technical modifications necessary to circumvent + Effective Technological Measures. For purposes of this + Public License, simply making modifications authorized by + this Section 2(a)(4) never produces Adapted Material. + - 5. Downstream recipients. + - A. Offer from the Licensor – Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + - B. No downstream restrictions. You may not offer or + impose any additional or different terms or conditions + on, or apply any Effective Technological Measures to, + the Licensed Material if doing so restricts exercise of + the Licensed Rights by any recipient of the Licensed + Material. + - 6. No endorsement. Nothing in this Public License + constitutes or may be construed as permission to assert or + imply that You are, or that Your use of the Licensed + Material is, connected with, or sponsored, endorsed, or + granted official status by, the Licensor or others + designated to receive attribution as provided in Section + 3(a)(1)(A)(i). + - b. Other rights. + - 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, + to the extent possible, the Licensor waives and/or agrees + not to assert any such rights held by the Licensor to the + limited extent necessary to allow You to exercise the + Licensed Rights, but not otherwise. + - 2. Patent and trademark rights are not licensed under this + Public License. + - 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + +- Section 3 – License Conditions. + + Your exercise of the Licensed Rights is expressly made subject to + the following conditions. + + - a. Attribution. + - 1. If You Share the Licensed Material (including in modified + form), You must: + - A. retain the following if it is supplied by the + Licensor with the Licensed Material: + - i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if designated); + - ii. a copyright notice; + - iii. a notice that refers to this Public License; + - iv. a notice that refers to the disclaimer of + warranties; + - v. a URI or hyperlink to the Licensed Material to + the extent reasonably practicable; + - B. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + - C. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + - 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may + be reasonable to satisfy the conditions by providing a URI + or hyperlink to a resource that includes the required + information. + - 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + - 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + +- Section 4 – Sui Generis Database Rights. + + Where the Licensed Rights include Sui Generis Database Rights that + apply to Your use of the Licensed Material: + + - a. for the avoidance of doubt, Section 2(a)(1) grants You the + right to extract, reuse, reproduce, and Share all or a + substantial portion of the contents of the database for + NonCommercial purposes only; + - b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; + and + - c. You must comply with the conditions in Section 3(a) if You + Share all or a substantial portion of the contents of the + database. + + For the avoidance of doubt, this Section 4 supplements and does not + replace Your obligations under this Public License where the + Licensed Rights include other Copyright and Similar Rights. + +- Section 5 – Disclaimer of Warranties and Limitation of Liability. + + - a. Unless otherwise separately undertaken by the Licensor, to + the extent possible, the Licensor offers the Licensed Material + as-is and as-available, and makes no representations or + warranties of any kind concerning the Licensed Material, whether + express, implied, statutory, or other. This includes, without + limitation, warranties of title, merchantability, fitness for a + particular purpose, non-infringement, absence of latent or other + defects, accuracy, or the presence or absence of errors, whether + or not known or discoverable. Where disclaimers of warranties + are not allowed in full or in part, this disclaimer may not + apply to You. + - b. To the extent possible, in no event will the Licensor be + liable to You on any legal theory (including, without + limitation, negligence) or otherwise for any direct, special, + indirect, incidental, consequential, punitive, exemplary, or + other losses, costs, expenses, or damages arising out of this + Public License or use of the Licensed Material, even if the + Licensor has been advised of the possibility of such losses, + costs, expenses, or damages. Where a limitation of liability is + not allowed in full or in part, this limitation may not apply to + You. + - c. The disclaimer of warranties and limitation of liability + provided above shall be interpreted in a manner that, to the + extent possible, most closely approximates an absolute + disclaimer and waiver of all liability. + +- Section 6 – Term and Termination. + + - a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply + with this Public License, then Your rights under this Public + License terminate automatically. + - b. Where Your right to use the Licensed Material has terminated + under Section 6(a), it reinstates: + + - 1. automatically as of the date the violation is cured, + provided it is cured within 30 days of Your discovery of the + violation; or + - 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect + any right the Licensor may have to seek remedies for Your + violations of this Public License. + + - c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing + so will not terminate this Public License. + - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + +- Section 7 – Other Terms and Conditions. + + - a. The Licensor shall not be bound by any additional or + different terms or conditions communicated by You unless + expressly agreed. + - b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + +- Section 8 – Interpretation. + + - a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could + lawfully be made without permission under this Public License. + - b. To the extent possible, if any provision of this Public + License is deemed unenforceable, it shall be automatically + reformed to the minimum extent necessary to make it enforceable. + If the provision cannot be reformed, it shall be severed from + this Public License without affecting the enforceability of the + remaining terms and conditions. + - c. No term or condition of this Public License will be waived + and no failure to comply consented to unless expressly agreed to + by the Licensor. + - d. Nothing in this Public License constitutes or may be + interpreted as a limitation upon, or waiver of, any privileges + and immunities that apply to the Licensor or You, including from + the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, +Creative Commons may elect to apply one of its public licenses to +material it publishes and in those instances will be considered the +"Licensor." The text of the Creative Commons public licenses is +dedicated to the public domain under the CC0 Public Domain Dedication. +Except for the limited purpose of indicating that material is shared +under a Creative Commons public license or as otherwise permitted by the +Creative Commons policies published at creativecommons.org/policies, +Creative Commons does not authorize the use of the trademark "Creative +Commons" or any other trademark or logo of Creative Commons without its +prior written consent including, without limitation, in connection with +any unauthorized modifications to any of its public licenses or any +other arrangements, understandings, or agreements concerning use of +licensed material. For the avoidance of doubt, this paragraph does not +form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/docs/API/available_datasets.md b/docs/API/available_datasets.md deleted file mode 100644 index fa630b8a..00000000 --- a/docs/API/available_datasets.md +++ /dev/null @@ -1,3 +0,0 @@ -# Available Datasets - -::: openqdc.datasets diff --git a/docs/API/basedataset.md b/docs/API/basedataset.md new file mode 100644 index 00000000..cdaeee77 --- /dev/null +++ b/docs/API/basedataset.md @@ -0,0 +1 @@ +::: openqdc.datasets.base diff --git a/docs/API/datasets/alchemy.md b/docs/API/datasets/alchemy.md new file mode 100644 index 00000000..096774c3 --- /dev/null +++ b/docs/API/datasets/alchemy.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.alchemy diff --git a/docs/API/datasets/ani.md b/docs/API/datasets/ani.md new file mode 100644 index 00000000..4f79f587 --- /dev/null +++ b/docs/API/datasets/ani.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.ani diff --git a/docs/API/datasets/comp6.md b/docs/API/datasets/comp6.md new file mode 100644 index 00000000..e473e211 --- /dev/null +++ b/docs/API/datasets/comp6.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.comp6 diff --git a/docs/API/datasets/des.md b/docs/API/datasets/des.md new file mode 100644 index 00000000..dbff5035 --- /dev/null +++ b/docs/API/datasets/des.md @@ -0,0 +1 @@ +::: openqdc.datasets.interaction.des diff --git a/docs/API/datasets/gdml.md b/docs/API/datasets/gdml.md new file mode 100644 index 00000000..a91cf993 --- /dev/null +++ b/docs/API/datasets/gdml.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.gdml diff --git a/docs/API/datasets/geom.md b/docs/API/datasets/geom.md new file mode 100644 index 00000000..f290eb93 --- /dev/null +++ b/docs/API/datasets/geom.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.geom.GEOM diff --git a/docs/API/datasets/iso_17.md b/docs/API/datasets/iso_17.md new file mode 100644 index 00000000..01a04e67 --- /dev/null +++ b/docs/API/datasets/iso_17.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.iso_17 diff --git a/docs/API/datasets/l7.md b/docs/API/datasets/l7.md new file mode 100644 index 00000000..512e7f37 --- /dev/null +++ b/docs/API/datasets/l7.md @@ -0,0 +1 @@ +::: openqdc.datasets.interaction.l7 diff --git a/docs/API/datasets/md22.md b/docs/API/datasets/md22.md new file mode 100644 index 00000000..d793b5cf --- /dev/null +++ b/docs/API/datasets/md22.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.md22 diff --git a/docs/API/datasets/metcalf.md b/docs/API/datasets/metcalf.md new file mode 100644 index 00000000..58566b02 --- /dev/null +++ b/docs/API/datasets/metcalf.md @@ -0,0 +1 @@ +::: openqdc.datasets.interaction.metcalf diff --git a/docs/API/datasets/molecule3d.md b/docs/API/datasets/molecule3d.md new file mode 100644 index 00000000..d7b6a5a4 --- /dev/null +++ b/docs/API/datasets/molecule3d.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.molecule3d diff --git a/docs/API/datasets/multixcqm9.md b/docs/API/datasets/multixcqm9.md new file mode 100644 index 00000000..55993cd7 --- /dev/null +++ b/docs/API/datasets/multixcqm9.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.multixcqm9 diff --git a/docs/API/datasets/nabladft.md b/docs/API/datasets/nabladft.md new file mode 100644 index 00000000..a69d68d7 --- /dev/null +++ b/docs/API/datasets/nabladft.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.nabladft diff --git a/docs/API/datasets/orbnet_denali.md b/docs/API/datasets/orbnet_denali.md new file mode 100644 index 00000000..1b4ee6a7 --- /dev/null +++ b/docs/API/datasets/orbnet_denali.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.orbnet_denali diff --git a/docs/API/datasets/pcqm.md b/docs/API/datasets/pcqm.md new file mode 100644 index 00000000..6cd1b92b --- /dev/null +++ b/docs/API/datasets/pcqm.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.pcqm diff --git a/docs/API/datasets/proteinfragments.md b/docs/API/datasets/proteinfragments.md new file mode 100644 index 00000000..d5aa28a5 --- /dev/null +++ b/docs/API/datasets/proteinfragments.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.proteinfragments diff --git a/docs/API/datasets/qm1b.md b/docs/API/datasets/qm1b.md new file mode 100644 index 00000000..b92dfff4 --- /dev/null +++ b/docs/API/datasets/qm1b.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.qm1b diff --git a/docs/API/datasets/qm7x.md b/docs/API/datasets/qm7x.md new file mode 100644 index 00000000..d649b40d --- /dev/null +++ b/docs/API/datasets/qm7x.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.qm7x diff --git a/docs/API/datasets/qmugs.md b/docs/API/datasets/qmugs.md new file mode 100644 index 00000000..06773b68 --- /dev/null +++ b/docs/API/datasets/qmugs.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.qmugs diff --git a/docs/API/datasets/qmx.md b/docs/API/datasets/qmx.md new file mode 100644 index 00000000..b7343767 --- /dev/null +++ b/docs/API/datasets/qmx.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.qmx diff --git a/docs/API/datasets/revmd17.md b/docs/API/datasets/revmd17.md new file mode 100644 index 00000000..e63ba031 --- /dev/null +++ b/docs/API/datasets/revmd17.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.revmd17 diff --git a/docs/API/datasets/sn2_rxn.md b/docs/API/datasets/sn2_rxn.md new file mode 100644 index 00000000..9095532c --- /dev/null +++ b/docs/API/datasets/sn2_rxn.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.sn2_rxn diff --git a/docs/API/datasets/solvated_peptides.md b/docs/API/datasets/solvated_peptides.md new file mode 100644 index 00000000..a6139c12 --- /dev/null +++ b/docs/API/datasets/solvated_peptides.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.solvated_peptides diff --git a/docs/API/datasets/spice.md b/docs/API/datasets/spice.md new file mode 100644 index 00000000..c0e95b79 --- /dev/null +++ b/docs/API/datasets/spice.md @@ -0,0 +1,2 @@ + +::: openqdc.datasets.potential.spice diff --git a/docs/API/datasets/splinter.md b/docs/API/datasets/splinter.md new file mode 100644 index 00000000..00789cfa --- /dev/null +++ b/docs/API/datasets/splinter.md @@ -0,0 +1 @@ +::: openqdc.datasets.interaction.splinter diff --git a/docs/API/datasets/tmqm.md b/docs/API/datasets/tmqm.md new file mode 100644 index 00000000..70b56781 --- /dev/null +++ b/docs/API/datasets/tmqm.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.tmqm diff --git a/docs/API/datasets/transition1x.md b/docs/API/datasets/transition1x.md new file mode 100644 index 00000000..63eceaa3 --- /dev/null +++ b/docs/API/datasets/transition1x.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.transition1x diff --git a/docs/API/datasets/vqm24.md b/docs/API/datasets/vqm24.md new file mode 100644 index 00000000..ed117b9f --- /dev/null +++ b/docs/API/datasets/vqm24.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.vqm24 diff --git a/docs/API/datasets/waterclusters.md b/docs/API/datasets/waterclusters.md new file mode 100644 index 00000000..f1f90883 --- /dev/null +++ b/docs/API/datasets/waterclusters.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.waterclusters diff --git a/docs/API/datasets/waterclusters3_30.md b/docs/API/datasets/waterclusters3_30.md new file mode 100644 index 00000000..3f0ccf7f --- /dev/null +++ b/docs/API/datasets/waterclusters3_30.md @@ -0,0 +1 @@ +::: openqdc.datasets.potential.waterclusters3_30 diff --git a/docs/API/datasets/x40.md b/docs/API/datasets/x40.md new file mode 100644 index 00000000..799738c5 --- /dev/null +++ b/docs/API/datasets/x40.md @@ -0,0 +1 @@ +::: openqdc.datasets.interaction.x40 diff --git a/docs/API/formats.md b/docs/API/formats.md new file mode 100644 index 00000000..fab98169 --- /dev/null +++ b/docs/API/formats.md @@ -0,0 +1 @@ +::: openqdc.datasets.structure diff --git a/docs/API/methods.md b/docs/API/methods.md index 7814334e..ce1d94a4 100644 --- a/docs/API/methods.md +++ b/docs/API/methods.md @@ -1,3 +1,7 @@ # QM Methods -::: openqdc.methods +::: openqdc.methods.enums + +# Isolated Atom Energies + +::: openqdc.methods.atom_energies diff --git a/docs/API/regressor.md b/docs/API/regressor.md new file mode 100644 index 00000000..dff0ad98 --- /dev/null +++ b/docs/API/regressor.md @@ -0,0 +1 @@ +::: openqdc.utils.regressor diff --git a/docs/API/units.md b/docs/API/units.md new file mode 100644 index 00000000..0401bdc4 --- /dev/null +++ b/docs/API/units.md @@ -0,0 +1,3 @@ +# UNITS + +::: openqdc.utils.units diff --git a/docs/API/utils.md b/docs/API/utils.md new file mode 100644 index 00000000..35fae5c8 --- /dev/null +++ b/docs/API/utils.md @@ -0,0 +1 @@ +::: openqdc.utils diff --git a/docs/_overrides/main.html b/docs/_overrides/main.html deleted file mode 100644 index 2eafd76b..00000000 --- a/docs/_overrides/main.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -{{ super() }} - - -{% endblock content %} diff --git a/docs/assets/StorageView.png b/docs/assets/StorageView.png new file mode 100644 index 0000000000000000000000000000000000000000..8d39892678087db840f31381d495b4fc3c3ffa7b GIT binary patch literal 111109 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 E11<#p-T(jq literal 0 HcmV?d00001 diff --git a/docs/assets/qdc_logo.png b/docs/assets/qdc_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a8138dcc2429aacc72f302a81240473be0e0589b GIT binary patch literal 256743 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≻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�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

}Za2lP} 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 literal 0 HcmV?d00001 diff --git a/docs/cli.md b/docs/cli.md new file mode 100644 index 00000000..8e2cd53b --- /dev/null +++ b/docs/cli.md @@ -0,0 +1,113 @@ +# CLI for dataset downloading and uploading +You can quickly download, fetch, preprocess and upload openQDC datasets using the command line interface (CLI). + +## Datasets +Print a formatted table of the available openQDC datasets and some informations. + +Usage: + + openqdc datasets [OPTIONS] + +Options: + + --help Show this message and exit. + +## Cache +Get the current local cache path of openQDC + +Usage: + + openqdc cache [OPTIONS] + +Options: + + --help Show this message and exit. + + +## Download +Download preprocessed ml-ready datasets from the main openQDC hub. + +Usage: + + openqdc download DATASETS... [OPTIONS] + +Options: + + --help Show this message and exit. + --overwrite Whether to force the re-download of the datasets and overwrite the current cached dataset. [default: no-overwrite] + --cache-dir Path to the cache. If not provided, the default cache directory (.cache/openqdc/) will be used. [default: None] + --as-zarr Whether to use a zarr format for the datasets instead of memmap. [default: no-as-zarr] + --gs Whether source to use for downloading. If True, Google Storage will be used.Otherwise, AWS S3 will be used [default: no-gs] + +Example: + + openqdc download Spice + +## Fetch +Download the raw datasets files from the main openQDC hub + +Note: + + Special case: if the dataset is "all", "potential", "interaction". + +Usage: + + openqdc fetch DATASETS... [OPTIONS] + +Options: + + --help Show this message and exit. + --overwrite Whether to overwrite or force the re-download of the raw files. [default: no-overwrite] + --cache-dir Path to the cache. If not provided, the default cache directory (.cache/openqdc/) will be used. [default: None] + +Example: + + openqdc fetch Spice + +## Preprocess +Preprocess a raw dataset (previously fetched) into a openqdc dataset and optionally push it to remote. + +Usage: + + openqdc preprocess DATASETS... [OPTIONS] + +Options: + + --help Show this message and exit. + --overwrite Whether to overwrite the current cached datasets. [default: overwrite] + --upload Whether to attempt the upload to the remote storage. Must have write permissions. [default: no-upload] + --as-zarr Whether to preprocess as a zarr format or a memmap format. [default: no-as-zarr] + +Example: + + openqdc preprocess Spice QMugs + +## Upload +Upload a preprocessed dataset to the remote storage + +Usage: + + openqdc upload DATASETS... [OPTIONS] + +Options: + + --help Show this message and exit. + --overwrite Whether to overwrite the remote files if they are present. [default: overwrite] + --as-zarr Whether to upload the zarr files if available. [default: no-as-zarr] + +Example: + + openqdc upload Spice --overwrite + +## Convert +Convert a preprocessed dataset from a memmap dataset to a zarr dataset. + +Usage: + + openqdc convert DATASETS... [OPTIONS] + +Options: + + --help Show this message and exit. + --overwrite Whether to overwrite the current zarr cached datasets. [default: no-overwrite] + --download Whether to force the re-download of the memmap datasets. [default: no-download] diff --git a/docs/contribute.md b/docs/contribute.md new file mode 100644 index 00000000..e0e22721 --- /dev/null +++ b/docs/contribute.md @@ -0,0 +1,59 @@ +# Contribute + +The below documents the development lifecycle of OpenQDC. + +## Setup a dev environment + +```bash +mamba env create -n openqdc -f env.yml +mamba activate datamol +pip install -e . +``` + +## Pre commit installation + +```bash +pre-commit install +pre-commit run --all-files +``` + +## Continuous Integration + +OpenQDC uses Github Actions to: + +- **Build and test** `openQDC`. + - Multiple combinations of OS and Python versions are tested. +- **Check** the code: + - Formatting with `black`. + - Static type check with `mypy`. + - Modules import formatting with `isort`. + - Pre-commit hooks. +- **Documentation**: + - Google docstring format. + - build and deploy the documentation on `main` and for every new git tag. + + +## Run tests + +```bash +pytest +``` + +## Build the documentation + +You can build and serve the documentation locally with: + +```bash +# Build and serve the doc +mike serve +``` + +or with + +```bash +mkdocs serve +``` + +### Multi-versionning + +The doc is built for eash push on `main` and every git tags using [mike](https://github.com/jimporter/mike). Everything is automated using Github Actions. Please refer to the official mike's documentation for the details. diff --git a/docs/css/custom-openqdc.css b/docs/css/custom-openqdc.css new file mode 100644 index 00000000..a1d97cf7 --- /dev/null +++ b/docs/css/custom-openqdc.css @@ -0,0 +1,92 @@ +:root { + --openqdc-primary: ##201342; + --openqdc-secondary: #4A1E7E; + + /* Primary color shades */ + --md-primary-fg-color: var(--openqdc-primary); + --md-primary-fg-color--light: var(--openqdc-primary); + --md-primary-fg-color--dark: var(--openqdc-primary); + --md-primary-bg-color: var(--openqdc-secondary); + --md-primary-bg-color--light: var(--openqdc-secondary); + --md-text-link-color: var(--openqdc-secondary); + + /* Accent color shades */ + --md-accent-fg-color: var(--openqdc-secondary); + --md-accent-fg-color--transparent: var(--openqdc-secondary); + --md-accent-bg-color: var(--openqdc-secondary); + --md-accent-bg-color--light: var(--openqdc-secondary); + } + + :root>* { + /* Code block color shades */ + --md-code-bg-color: hsla(0, 0%, 96%, 1); + --md-code-fg-color: hsla(200, 18%, 26%, 1); + + /* Footer */ + --md-footer-bg-color: var(--openqdc-primary); + /* --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32); */ + --md-footer-fg-color: var(--openqdc-secondary); + --md-footer-fg-color--light: var(--openqdc-secondary); + --md-footer-fg-color--lighter: var(--openqdc-secondary); + + } + + .md-header { + background-image: linear-gradient(to right, #131036, #4A1E7E); + } + + .md-footer { + background-image: linear-gradient(to right, #131036, #4A1E7E); + } + + .md-tabs { + background-image: linear-gradient(to right, #F4F6F9, #b39bce); + } + + .md-header__topic { + color: rgb(255, 255, 255); + } + + .md-source__repository, + .md-source__icon, + .md-search__input, + .md-search__input::placeholder, + .md-search__input~.md-search__icon, + .md-footer__inner.md-grid, + .md-copyright__highlight, + .md-copyright, + .md-footer-meta.md-typeset a, + .md-version { + color: rgb(255, 255, 255) !important; + } + + .md-search__form { + background-color: rgba(255, 255, 255, 0.2); + } + + .md-search__input { + color: #222222 !important; + } + + .md-header__topic { + color: rgb(255, 255, 255); + font-size: 1.4em; + } + + /* Increase the size of the logo */ + .md-header__button.md-logo img, + .md-header__button.md-logo svg { + height: 2rem !important; + } + + /* Reduce the margin around the logo */ + .md-header__button.md-logo { + margin: 0.4em; + padding: 0.4em; + } + + /* Remove the `In` and `Out` block in rendered Jupyter notebooks */ + .md-container .jp-Cell-outputWrapper .jp-OutputPrompt.jp-OutputArea-prompt, + .md-container .jp-Cell-inputWrapper .jp-InputPrompt.jp-InputArea-prompt { + display: none !important; + } diff --git a/docs/data_storage.md b/docs/data_storage.md new file mode 100644 index 00000000..b24bec3b --- /dev/null +++ b/docs/data_storage.md @@ -0,0 +1,33 @@ +## Dataset structure + +For a dataset with N geometries, M atoms across all geometries, ne energy labels, +and nf force labels, we use zarr or memory-mapped arrays of various sizes: + +- (M, 5) for atomic numbers (1), +charges (1), and positions (3) of individual geometries; + +- (N, 2) for the beginning and end indices of +each geometry in the previous array; + +- (N, ne) for the energy labels of each geometry, extendable to +store other geometry-level QM properties such as HOMO-LUMO gap; + +- (M, nf , 3) for the force labels +of each geometry, extendable to store other atom-level QM properties. + + +The memory-mapped files efficiently access data stored on disk or in the cloud without reading +them into memory, enabling training on machines with smaller RAM than the dataset size and +accommodating concurrent reads in multi-GPU training. This allows for very efficient indexing, +batching and iteration. + +![](assets/StorageView.png) + + +## Formats + +We currently support the following formats: + +1) Zarr : https://zarr.readthedocs.io/en/stable/index.html + +2) Memmap : https://numpy.org/doc/stable/index.html diff --git a/docs/dataset_upload.md b/docs/dataset_upload.md new file mode 100644 index 00000000..e4740f75 --- /dev/null +++ b/docs/dataset_upload.md @@ -0,0 +1,69 @@ +# How to Add a Dataset to OpenQDC + +Do you think that OpenQDC is missing some important dataset? Do you think your dataset would be a good fit for OpenQDC? +If so, you can contribute to OpenQDC by adding your dataset to the OpenQDC repository in two ways: + +1. Opening a PR to add a new dataset +2. Request a new dataset through Google Form + +## OpenQDC PR Guidelines + +Implement your dataset in the OpenQDC repository by following the guidelines below: + +### Dataset class + +- The dataset class should be implemented in the `openqdc/datasets` directory. +- The dataset class should inherit from the `openqdc.datasets.base.BaseDataset` class. +- Add your `dataset.py` file to the `openqdc/datasets/potential` or `openqdc/datasets/interaction/` directory based on the type of energy. +- Implement the following for your dataset: + - Add the metadata of the dataset: + - Docstrings for the dataset class. Docstrings should report links and references to the dataset. A small description and if possible, the sampling strategy used to generate the dataset. + - `__links__`: Dictionary of name and link to download the dataset. + - `__name__`: Name of the dataset. This will create a folder with the name of the dataset in the cache directory. + - The original units for the dataset `__energy_unit__` and `__distance_unit__`. + - `__force_mask__`: Boolean to indicate if the dataset has forces. Or if multiple forces are present. A list of booleans. + - `__energy_methods__`: List of the `QmMethod` methods present in the dataset. + - `read_raw_entries(self)` -> `List[Dict[str, Any]]`: Preprocess the raw dataset and return a list of dictionaries containing the data. For a better overview of the data format. Look at data storage. This data should have the following keys: + - `atomic_inputs` : Atomic inputs of the molecule. numpy.Float32. + - `name`: Atomic numbers of the atoms in the molecule. numpy.Object. + - `subset`: Positions of the atoms in the molecule. numpy.Object. + - `energies`: Energies of the molecule. numpy.Float64. + - `n_atoms`: Number of atoms in the molecule. numpy.Int32 + - `forces`: Forces of the molecule. [Optional] numpy.Float32. + - Add the dataset import to the `openqdc/datasets//__init__.py` file and to `openqdc/__init__.py`. + +### Test the dataset + +Try to run the openQDC CLI pipeline with the dataset you implemented. + +Run the following command to download the dataset: + +- Fetch the dataset files +```bash +openqdc fetch DATASET_NAME +``` + +- Preprocess the dataset +```bash +openqdc preprocess DATASET_NAME +``` + +- Load it on python and check if the dataset is correctly loaded. +```python +from openqdc import DATASET_NAME +ds=DATASET_NAME() +``` + +If the dataset is correctly loaded, you can open a PR to add the dataset to OpenQDC. + +- Select for your PR the `dataset` label. + +Our team will review your PR and provide feedback if necessary. If everything is correct, your dataset will be added to OpenQDC remote storage. + +## OpenQDC Google Form + +Alternatively, you can ask the OpenQDC main development team to take care of the dataset upload for you. +You can fill out the Google Form [here](https://docs.google.com/forms/d/e/1FAIpQLSeh0YHRn-OoqPpUbrL7G-EOu3LtZC24rtQWwbjJaZ-2V8P2vQ/viewform?usp=sf_link) + +As the openQDC team will strive to provide a high quality curation and upload, +please be patient as the team will need to review the dataset and carry out the necessary steps to ensure the dataset is uploaded correctly. diff --git a/docs/index.md b/docs/index.md index 264211f1..db497b10 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,30 +1,65 @@ -# openQDC +# Overview -Open Quantum Data Commons +OpenQDC is a python library to work with quantum datasets. It's a package aimed at providing a simple and efficient way to download, load and utilize various datasets and provide a way to standardize the data for easy use in machine learning models. -## Setup Datasets +- 🐍 Simple pythonic API +- 🕹️ ML-Ready: all you manipulate are `torch.Tensor`,`jax.Array` or `numpy.Array`objects. +- ⚛️ Quantum Ready: The quantum methods are checked and standardized to provide addictional values. +- ✅ Standardized: The datasets are written in standard and performant formats with annotated metadata like units and labels. +- 🧠 Performance matters: read and write multiple formats (memmap, zarr, xyz, etc). +- 📈 Data: have access to 1.5+ billion datapoints -Use the scripts in `setup/` to download the datasets. For more information, see the [README](setup/README.md) in the `setup/` directory. +Visit our website at TOFILL . + +## Installation + +Use mamba: -# Install the library in dev mode ```bash -# Install the deps -mamba env create -n qdc -f env.yml +mamba install -c conda-forge openqdc +``` -# Activate the environment -mamba activate qdc +_**Tips:** You can replace `mamba` by `conda`._ -# Install the qdc library in dev mode -pip install -e . +_**Note:** We highly recommend using a [Conda Python distribution](https://github.com/conda-forge/miniforge) to install OpenQDC. The package is also pip installable if you need it: `pip install openqdc`._ -``` +## Quick API Tour -## Development lifecycle +```python +from openqdc as Spice -### Tests +# Load the original dataset +dataset = Spice() -You can run tests locally with: +# Load the dataset with a different units +dataset = Spice( + energy_unit = "kcal/mol", + distance_unit = "ang", + energy_type = "formation", + array_format = "torch" +) -```bash -pytest . +# Access the data +data = dataset[0] + +# Get relevant statistics +dataset.get_statistics() + +# Get dataset metadata +dataset.average_n_atoms +dataset.chemical_species +dataset.charges + +# Compute physical descriptors +dataset.calculate_descriptors( + descriptor_name = "soap" +) ``` + +## How to cite + +Please cite OpenQDC if you use it in your research: [![DOI](zenodo_badge)](zenodo_link). + +## Compatibilities + +OpenQDC is compatible with Python >= 3.8 and is tested on Linux, MacOS and Windows. diff --git a/docs/licensing.md b/docs/licensing.md new file mode 100644 index 00000000..ec5a3857 --- /dev/null +++ b/docs/licensing.md @@ -0,0 +1,3 @@ +``` +{!LICENSE!} +``` diff --git a/docs/normalization_e0s.md b/docs/normalization_e0s.md new file mode 100644 index 00000000..426e7d0d --- /dev/null +++ b/docs/normalization_e0s.md @@ -0,0 +1,38 @@ +# Overview of QM Methods and Normalization + +OpenQDC provides support for 250+ QM Methods and provides a way to standardize and categorize +the usage of different level of theories used for Quantum Mechanics Single Point Calculations +to add value and information to the datasets. + +## Level of Theory + +To avoid inconsistencies, level of theories are standardized and categorized into Python Enums +consisting of a functional, a basis set, and a correction method. +OpenQDC covers more than 106 functionals, 20 basis sets, and 11 +correction methods. +OpenQDC provides the computed the isolated atom energies `e0` for each QM method. + + +## Normalization + + +We provide support of energies through "physical" and "regression" normalization to conserve the size extensivity of chemical systems. +OpenQDC through this normalization, provide a way to transform the potential energy to atomization energy by subtracting isolated atom energies `e0` +physically interpretable and extensivity-conserving normalization method. Alternatively, we pre- +compute the average contribution of each atom species to potential energy via linear or ridge +regression, centering the distribution at 0 and providing uncertainty estimation for the computed +values. Predicted atomic energies can also be scaled to approximate a standard normal distribution. + +### Physical Normalization + +`e0` energies are calculated for each atom in the dataset at the appropriate level of theory and then subtracted from +the potential energy to obtain the atomization energy. This normalization method is physically interpretable and +only remove the atom energy contribution from the potential energy. + + +### Regression Normalization + +`e0` energies are calculated for each atom in the dataset from fitting a regression model to the potential energy. +The `e0` energies are then subtracted from the potential energy to obtain the atomization energy. This normalization +provides uncertainty estimation for the computed values and remove part of the interatomic energy contribution from the potential energy. +The resulting formation energy is centered at 0. diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 00000000..af62f453 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,42 @@ +# Usage + +## How to use + +OpenQDC has been designed to be used with a single import: + +```python +import openqdc as qdc +dataset = qdc.QM9() +``` + +All `openQDC` functions are available under `qdc`. +Or if you want to directly import a specific dataset: + +```python +from openqdc as Spice +# Spice dataset with distance unit in angstrom instead of bohr +dataset = Spice(distance_unit="ang", + array_format = "jax" +) +dataset[0] # dict of jax array +``` + +Or if you prefer handling `ase.Atoms` objects: + +```python +dataset.get_ase_atoms(0) +``` + +## Iterators + +OpenQDC provides a simple way to get the data as iterators: + +```python +for data in dataset.as_iter(atoms=True): + print(data) # Atoms object + break +``` + +## Lazy loading + +OpenQDC uses lazy loading to dynamically expose all its API without imposing a long import time during `import openqdc as qdc`. In case of trouble you can always disable lazy loading by setting the environment variable `OPENQDC_DISABLE_LAZY_LOADING` to `1`. diff --git a/env.yml b/env.yml index 16ccc3c2..87a9ccac 100644 --- a/env.yml +++ b/env.yml @@ -11,10 +11,15 @@ dependencies: - gcsfs - typer - prettytable + - s3fs + - pydantic + - python-dotenv + # Scientific - pandas - numpy + - zarr # Chem - datamol #==0.9.0 @@ -36,6 +41,7 @@ dependencies: - ruff # Doc + - mike - mkdocs - mkdocs-material - mkdocs-material-extensions diff --git a/mkdocs.yml b/mkdocs.yml index caac43c9..fdb8856a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,39 +1,91 @@ -site_name: "Open Quantum Data Commons (openQDC)" +site_name: "OpenQDC" site_description: "I don't know... Something about data and Quantum stuff I guess :D" -site_url: "https://github.com/OpenDrugDiscovery/openQDC" repo_url: "https://github.com/OpenDrugDiscovery/openQDC" repo_name: "openQDC" copyright: Copyright 2023 Valence Labs +site_url: "https://github.com/OpenDrugDiscovery/openQDC" remote_branch: "privpage" use_directory_urls: false docs_dir: "docs" +# Fail on warnings to detect issues with types and docstring +strict: true + nav: - Overview: index.md + - Usage: + - Base usage : usage.md + - CLI: cli.md - Available Datasets: datasets.md - #- Tutorials: - # #- Really hard example: tutorials/usage.ipynb + - QM methods: normalization_e0s.md + - Data structure: data_storage.md + - Tutorials: + - Really hard example: tutorials/usage.ipynb - API: - - Datasets: API/available_datasets.md - - Isolated Atoms Energies: API/isolated_atom_energies.md + - QM methods: API/methods.md + - Normalization regressor: API/regressor.md + - Main class: API/basedataset.md + - Format loading: API/formats.md + - Datasets: + - Potential Energy: + - Alchemy : API/datasets/alchemy.md + - ANI : API/datasets/ani.md + - Spice : API/datasets/spice.md + - GEOM : API/datasets/geom.md + - Qmugs : API/datasets/qmugs.md + - ISO_17 : API/datasets/iso_17.md + - Comp6 : API/datasets/comp6.md + - GDML : API/datasets/gdml.md + - Molecule3D : API/datasets/molecule3d.md + - Orbnet Denali : API/datasets/orbnet_denali.md + - SN2 RXN : API/datasets/sn2_rxn.md + - QM7X : API/datasets/qm7x.md + - QM1B : API/datasets/qm1b.md + - NablaDFT : API/datasets/nabladft.md + - Solvated Peptides : API/datasets/solvated_peptides.md + - Waterclusters3_30 : API/datasets/waterclusters3_30.md + - SCAN Waterclusters : API/datasets/waterclusters.md + - TMQM : API/datasets/tmqm.md + - PCQM : API/datasets/pcqm.md + - RevMD17 : API/datasets/revmd17.md + - MD22 : API/datasets/md22.md + - Transition1X : API/datasets/transition1x.md + - MultixcQM9 : API/datasets/multixcqm9.md + - QMX : API/datasets/qmx.md + - Protein Fragments : API/datasets/proteinfragments.md + - VQM24 : API/datasets/vqm24.md + - Interaction Energy: + - DES : API/datasets/des.md + - L7 : API/datasets/l7.md + - X40 : API/datasets/x40.md + - Metcalf : API/datasets/metcalf.md + - Splinter : API/datasets/splinter.md + - Units: API/units.md + - Utils: API/utils.md + - Contribute: + - Mantaining: contribute.md + - Add a dataset: dataset_upload.md + - License: licensing.md + theme: name: material - custom_dir: docs/_overrides - palette: - primary: teal - accent: purple + #custom_dir: docs/_overrides features: - navigation.tabs - - navigation.expand + #- navigation.expand + #favicon: assets/qdc_logo.png + logo: assets/qdc_logo.png extra_css: - css/custom.css + - css/custom-openqdc.css extra_javascript: - javascripts/config.js - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js + #- https://unpkg.com/mermaid@10.9.0/dist/mermaid.min.js markdown_extensions: - admonition @@ -53,11 +105,14 @@ markdown_extensions: - toc: permalink: true +watch: + - openqdc/ + plugins: - search - mkdocstrings: - watch: - - openqdc/ + #watch: + # - openqdc/ handlers: python: setup_commands: @@ -69,7 +124,11 @@ plugins: rendering: show_root_heading: yes heading_level: 3 - show_if_no_docstring: true + show_if_no_docstring: false - mkdocs-jupyter: execute: False # kernel_name: python3 + +extra: + version: + provider: mike diff --git a/openqdc/__init__.py b/openqdc/__init__.py index 7e2eb2cf..c6be72d4 100644 --- a/openqdc/__init__.py +++ b/openqdc/__init__.py @@ -15,6 +15,7 @@ def get_project_root(): "__version__": "openqdc._version", "BaseDataset": "openqdc.datasets.base", # POTENTIAL + "Alchemy": "openqdc.datasets.potential.alchemy", "ANI1": "openqdc.datasets.potential.ani", "ANI1CCX": "openqdc.datasets.potential.ani", "ANI1CCX_V2": "openqdc.datasets.potential.ani", @@ -39,6 +40,7 @@ def get_project_root(): "NablaDFT": "openqdc.datasets.potential.nabladft", "SolvatedPeptides": "openqdc.datasets.potential.solvated_peptides", "WaterClusters": "openqdc.datasets.potential.waterclusters3_30", + "SCANWaterClusters": "openqdc.datasets.potential.waterclusters", "TMQM": "openqdc.datasets.potential.tmqm", "PCQM_B3LYP": "openqdc.datasets.potential.pcqm", "PCQM_PM6": "openqdc.datasets.potential.pcqm", @@ -47,6 +49,13 @@ def get_project_root(): "Transition1X": "openqdc.datasets.potential.transition1x", "MultixcQM9": "openqdc.datasets.potential.multixcqm9", "MultixcQM9_V2": "openqdc.datasets.potential.multixcqm9", + "QM7": "openqdc.datasets.potential.qmx", + "QM7b": "openqdc.datasets.potential.qmx", + "QM8": "openqdc.datasets.potential.qmx", + "QM9": "openqdc.datasets.potential.qmx", + "ProteinFragments": "openqdc.datasets.potential.proteinfragments", + "MDDataset": "openqdc.datasets.potential.proteinfragments", + "VQM24": "openqdc.datasets.potential.vqm24", # INTERACTION "DES5M": "openqdc.datasets.interaction.des", "DES370K": "openqdc.datasets.interaction.des", @@ -58,6 +67,7 @@ def get_project_root(): "Splinter": "openqdc.datasets.interaction.splinter", # DEBUG "Dummy": "openqdc.datasets.potential.dummy", + "PredefinedDataset": "openqdc.datasets.potential.dummy", # ALL "AVAILABLE_DATASETS": "openqdc.datasets", "AVAILABLE_POTENTIAL_DATASETS": "openqdc.datasets.potential", @@ -105,9 +115,10 @@ def __dir__(): from .datasets.interaction.x40 import X40 # POTENTIAL + from .datasets.potential.alchemy import Alchemy from .datasets.potential.ani import ANI1, ANI1CCX, ANI1CCX_V2, ANI1X, ANI2X from .datasets.potential.comp6 import COMP6 - from .datasets.potential.dummy import Dummy + from .datasets.potential.dummy import Dummy, PredefinedDataset from .datasets.potential.gdml import GDML from .datasets.potential.geom import GEOM from .datasets.potential.iso_17 import ISO17 @@ -117,13 +128,17 @@ def __dir__(): from .datasets.potential.nabladft import NablaDFT from .datasets.potential.orbnet_denali import OrbnetDenali from .datasets.potential.pcqm import PCQM_B3LYP, PCQM_PM6 + from .datasets.potential.proteinfragments import MDDataset, ProteinFragments from .datasets.potential.qm1b import QM1B, QM1B_SMALL from .datasets.potential.qm7x import QM7X, QM7X_V2 from .datasets.potential.qmugs import QMugs, QMugs_V2 + from .datasets.potential.qmx import QM7, QM8, QM9, QM7b from .datasets.potential.revmd17 import RevMD17 from .datasets.potential.sn2_rxn import SN2RXN from .datasets.potential.solvated_peptides import SolvatedPeptides from .datasets.potential.spice import Spice, SpiceV2, SpiceVL2 from .datasets.potential.tmqm import TMQM from .datasets.potential.transition1x import Transition1X + from .datasets.potential.vqm24 import VQM24 + from .datasets.potential.waterclusters import SCANWaterClusters from .datasets.potential.waterclusters3_30 import WaterClusters diff --git a/openqdc/cli.py b/openqdc/cli.py index 1d985090..7b32c9ae 100644 --- a/openqdc/cli.py +++ b/openqdc/cli.py @@ -1,3 +1,4 @@ +import os from typing import List, Optional import typer @@ -12,27 +13,40 @@ AVAILABLE_INTERACTION_DATASETS, AVAILABLE_POTENTIAL_DATASETS, ) +from openqdc.utils.io import get_local_cache app = typer.Typer(help="OpenQDC CLI") def sanitize(dictionary): + """ + Sanitize dataset names to be used in the CLI. + """ return {k.lower().replace("_", "").replace("-", ""): v for k, v in dictionary.items()} SANITIZED_AVAILABLE_DATASETS = sanitize(AVAILABLE_DATASETS) -def exist_dataset(dataset): +def exist_dataset(dataset) -> bool: + """ + Check if dataset is available in the openQDC datasets. + """ if dataset not in sanitize(AVAILABLE_DATASETS): logger.error(f"{dataset} is not available. Please open an issue on Github for the team to look into it.") return False return True -def format_entry(empty_dataset): +def format_entry(empty_dataset, max_num_to_display: int = 6): + """ + Format the entry for the table. + max_num_to_display: int = 6, + Maximum number of energy methods to display. Used to keep the table format + readable in case of datasets with many energy methods. [ex. MultiXQM9] + """ energy_methods = [str(x) for x in empty_dataset.__energy_methods__] - max_num_to_display = 6 + if len(energy_methods) > 6: entry = ",".join(energy_methods[:max_num_to_display]) + "..." else: @@ -46,7 +60,7 @@ def download( overwrite: Annotated[ bool, typer.Option( - help="Whether to overwrite or force the re-download of the datasets.", + help="Whether to force the re-download of the datasets and overwrite the current cached dataset.", ), ] = False, cache_dir: Annotated[ @@ -55,6 +69,19 @@ def download( help="Path to the cache. If not provided, the default cache directory (.cache/openqdc/) will be used.", ), ] = None, + as_zarr: Annotated[ + bool, + typer.Option( + help="Whether to use a zarr format for the datasets instead of memmap.", + ), + ] = False, + gs: Annotated[ + bool, + typer.Option( + help="Whether source to use for downloading. If True, Google Storage will be used." + + "Otherwise, AWS S3 will be used", + ), + ] = False, ): """ Download preprocessed ml-ready datasets from the main openQDC hub. @@ -62,18 +89,25 @@ def download( Example: openqdc download Spice QMugs """ + if gs: + os.environ["OPENQDC_DOWNLOAD_API"] = "gs" + for dataset in list(map(lambda x: x.lower().replace("_", ""), datasets)): if exist_dataset(dataset): - if SANITIZED_AVAILABLE_DATASETS[dataset].no_init().is_cached() and not overwrite: + ds = SANITIZED_AVAILABLE_DATASETS[dataset].no_init() + ds.read_as_zarr = as_zarr + if ds.is_cached() and not overwrite: logger.info(f"{dataset} is already cached. Skipping download") else: - SANITIZED_AVAILABLE_DATASETS[dataset](overwrite_local_cache=True, cache_dir=cache_dir) + SANITIZED_AVAILABLE_DATASETS[dataset]( + overwrite_local_cache=True, cache_dir=cache_dir, read_as_zarr=as_zarr, skip_statistics=True + ) @app.command() def datasets(): """ - Print a table of the available openQDC datasets and some informations. + Print a formatted table of the available openQDC datasets and some informations. """ table = PrettyTable(["Name", "Type of Energy", "Forces", "Level of theory"]) for dataset in AVAILABLE_DATASETS: @@ -98,7 +132,7 @@ def fetch( overwrite: Annotated[ bool, typer.Option( - help="Whether to overwrite or force the re-download of the files.", + help="Whether to overwrite or force the re-download of the raw files.", ), ] = False, cache_dir: Annotated[ @@ -109,17 +143,14 @@ def fetch( ] = None, ): """ - Download the raw datasets files from the main openQDC hub. - overwrite: bool = False, - If True, the files will be re-downloaded and overwritten. - cache_dir: Optional[str] = None, - Path to the cache. If not provided, the default cache directory will be used. - Special case: if the dataset is "all", "potential", "interaction". - all: all available datasets will be downloaded. - potential: all the potential datasets will be downloaded - interaction: all the interaction datasets will be downloaded - Example: - openqdc fetch Spice + Download the raw datasets files from the main openQDC hub.\n + Special case: if the dataset is "all", "potential", "interaction".\n + all: all available datasets will be downloaded.\n + potential: all the potential datasets will be downloaded\n + interaction: all the interaction datasets will be downloaded\n\n + + Example:\n + openqdc fetch Spice """ if datasets[0].lower() == "all": dataset_names = list(sanitize(AVAILABLE_DATASETS).keys()) @@ -143,18 +174,27 @@ def preprocess( overwrite: Annotated[ bool, typer.Option( - help="Whether to overwrite or force the re-download of the datasets.", + help="Whether to overwrite the current cached datasets.", ), ] = True, upload: Annotated[ bool, typer.Option( - help="Whether to try the upload to the remote storage.", + help="Whether to attempt the upload to the remote storage. Must have write permissions.", + ), + ] = False, + as_zarr: Annotated[ + bool, + typer.Option( + help="Whether to preprocess as a zarr format or a memmap format.", ), ] = False, ): """ Preprocess a raw dataset (previously fetched) into a openqdc dataset and optionally push it to remote. + + Example: + openqdc preprocess Spice QMugs """ for dataset in list(map(lambda x: x.lower().replace("_", ""), datasets)): if exist_dataset(dataset): @@ -166,5 +206,137 @@ def preprocess( raise e +@app.command() +def upload( + datasets: List[str], + overwrite: Annotated[ + bool, + typer.Option( + help="Whether to overwrite the remote files if they are present.", + ), + ] = True, + as_zarr: Annotated[ + bool, + typer.Option( + help="Whether to upload the zarr files if available.", + ), + ] = False, +): + """ + Upload a preprocessed dataset to the remote storage. + + Example: + openqdc upload Spice --overwrite + """ + for dataset in list(map(lambda x: x.lower().replace("_", ""), datasets)): + if exist_dataset(dataset): + logger.info(f"Uploading {SANITIZED_AVAILABLE_DATASETS[dataset].__name__}") + try: + SANITIZED_AVAILABLE_DATASETS[dataset](skip_statistics=True).upload(overwrite=overwrite, as_zarr=as_zarr) + except Exception as e: + logger.error(f"Error while uploading {dataset}. {e}. Did you preprocess the dataset first?") + raise e + + +@app.command() +def convert( + datasets: List[str], + overwrite: Annotated[ + bool, + typer.Option( + help="Whether to overwrite the current zarr cached datasets.", + ), + ] = False, + download: Annotated[ + bool, + typer.Option( + help="Whether to force the re-download of the memmap datasets.", + ), + ] = False, +): + """ + Convert a preprocessed dataset from a memmap dataset to a zarr dataset. + """ + import os + from os.path import join as p_join + + import numpy as np + import zarr + + from openqdc.utils.io import load_pkl + + def silent_remove(filename): + """ + Zarr zip files are currently not overwritable. This function is used to remove the file if it exists. + """ + try: + os.remove(filename) + except OSError: + pass + + for dataset in list(map(lambda x: x.lower().replace("_", ""), datasets)): + if exist_dataset(dataset): + logger.info(f"Converting {SANITIZED_AVAILABLE_DATASETS[dataset].__name__}") + try: + ds = SANITIZED_AVAILABLE_DATASETS[dataset](overwrite_local_cache=download, skip_statistics=True) + # os.makedirs(p_join(ds.root, "zips", ds.__name__), exist_ok=True) + + pkl = load_pkl(p_join(ds.preprocess_path, "props.pkl")) + metadata = p_join(ds.preprocess_path, "metadata.zip") + if overwrite: + silent_remove(metadata) + group = zarr.group(zarr.storage.ZipStore(metadata)) + for key, value in pkl.items(): + # sub=group.create_group(key) + if key in ["name", "subset"]: + data = group.create_dataset(key, shape=value[0].shape, dtype=value[0].dtype) + data[:] = value[0][:] + data2 = group.create_dataset(key + "_ptr", shape=value[1].shape, dtype=np.int32) + data2[:] = value[1][:] + else: + data = group.create_dataset(key, shape=value.shape, dtype=value.dtype) + data[:] = value[:] + + force_attrs = { + "unit": str(ds.force_unit), + "level_of_theory": ds.force_methods, + } + + energy_attrs = {"unit": str(ds.energy_unit), "level_of_theory": ds.energy_methods} + + atomic_inputs_attrs = { + "unit": str(ds.distance_unit), + } + attrs = {"forces": force_attrs, "energies": energy_attrs, "atomic_inputs": atomic_inputs_attrs} + + # os.makedirs(p_join(ds.root, "zips", ds.__name__), exist_ok=True) + for key, value in ds.data.items(): + if key not in ds.data_keys: + continue + print(key, value.shape) + + zarr_path = p_join(ds.preprocess_path, key + ".zip") # ds.__name__, + if overwrite: + silent_remove(zarr_path) + z = zarr.open( + zarr.storage.ZipStore(zarr_path), "w", zarr_version=2, shape=value.shape, dtype=value.dtype + ) + z[:] = value[:] + if key in attrs: + z.attrs.update(attrs[key]) + + except Exception as e: + logger.error(f"Error while converting {dataset}. {e}. Did you preprocess the dataset first?") + raise e + + +@app.command() +def cache(): + """ + Get the current local cache path of openQDC + """ + print(f"openQDC local cache:\n {get_local_cache()}") + + if __name__ == "__main__": app() diff --git a/openqdc/datasets/base.py b/openqdc/datasets/base.py index 026bfd75..8a480125 100644 --- a/openqdc/datasets/base.py +++ b/openqdc/datasets/base.py @@ -1,13 +1,18 @@ """The BaseDataset defining shared functionality between all datasets.""" import os -import pickle as pkl + +try: + from collections.abc import Iterable +except ImportError: + from collections import Iterable from functools import partial from itertools import compress from os.path import join as p_join from typing import Callable, Dict, List, Optional, Union import numpy as np +from ase import Atoms from ase.io.extxyz import write_extxyz from loguru import logger from sklearn.utils import Bunch @@ -22,6 +27,7 @@ StatisticManager, TotalEnergyStats, ) +from openqdc.datasets.structure import MemMapDataset, ZarrDataset from openqdc.utils.constants import MAX_CHARGE, NB_ATOMIC_FEATURES from openqdc.utils.descriptors import get_descriptor from openqdc.utils.exceptions import ( @@ -32,7 +38,6 @@ copy_exists, dict_to_atoms, get_local_cache, - pull_locally, push_remote, set_cache_dir, ) @@ -76,6 +81,7 @@ class BaseDataset(DatasetPropertyMixIn): energy_target_names = [] force_target_names = [] + read_as_zarr = False __energy_methods__ = [] __force_mask__ = [] __isolated_atom_energies__ = [] @@ -99,7 +105,9 @@ def __init__( cache_dir: Optional[str] = None, recompute_statistics: bool = False, transform: Optional[Callable] = None, - regressor_kwargs={ + skip_statistics: bool = False, + read_as_zarr: bool = False, + regressor_kwargs: Dict = { "solver_type": "linear", "sub_sample": None, "stride": 1, @@ -107,29 +115,28 @@ def __init__( ) -> None: """ - Parameters - ---------- - energy_unit - Energy unit to convert dataset to. Supported units: ["kcal/mol", "kj/mol", "hartree", "ev"] - distance_unit - Distance unit to convert dataset to. Supported units: ["ang", "nm", "bohr"] - array_format - Format to return arrays in. Supported formats: ["numpy", "torch", "jax"] - energy_type - Type of isolated atom energy to use for the dataset. Default: "formation" - Supported types: ["formation", "regression", "null", None] - overwrite_local_cache - Whether to overwrite the locally cached dataset. - cache_dir - Cache directory location. Defaults to "~/.cache/openqdc" - recompute_statistics - Whether to recompute the statistics of the dataset. - transform, optional - transformation to apply to the __getitem__ calls - regressor_kwargs - Dictionary of keyword arguments to pass to the regressor. - Default: {"solver_type": "linear", "sub_sample": None, "stride": 1} - solver_type can be one of ["linear", "ridge"] + Parameters: + energy_unit: + Energy unit to convert dataset to. Supported units: ["kcal/mol", "kj/mol", "hartree", "ev"] + distance_unit: + Distance unit to convert dataset to. Supported units: ["ang", "nm", "bohr"] + array_format: + Format to return arrays in. Supported formats: ["numpy", "torch", "jax"] + energy_type: + Type of isolated atom energy to use for the dataset. Default: "formation" + Supported types: ["formation", "regression", "null", None] + overwrite_local_cache: + Whether to overwrite the locally cached dataset. + cache_dir: + Cache directory location. Defaults to "~/.cache/openqdc" + recompute_statistics: + Whether to recompute the statistics of the dataset. + transform: + transformation to apply to the __getitem__ calls + regressor_kwargs: + Dictionary of keyword arguments to pass to the regressor. + Default: {"solver_type": "linear", "sub_sample": None, "stride": 1} + solver_type can be one of ["linear", "ridge"] """ set_cache_dir(cache_dir) # self._init_lambda_fn() @@ -138,8 +145,10 @@ def __init__( self.recompute_statistics = recompute_statistics self.regressor_kwargs = regressor_kwargs self.transform = transform + self.read_as_zarr = read_as_zarr self.energy_type = energy_type if energy_type is not None else "null" self.refit_e0s = recompute_statistics or overwrite_local_cache + self.skip_statistics = skip_statistics if not self.is_preprocessed(): raise DatasetNotAvailableError(self.__name__) else: @@ -152,6 +161,12 @@ def _init_lambda_fn(self): self._fn_distance = lambda x: x self._fn_forces = lambda x: x + @property + def dataset_wrapper(self): + if not hasattr(self, "_dataset_wrapper"): + self._dataset_wrapper = ZarrDataset() if self.read_as_zarr else MemMapDataset() + return self._dataset_wrapper + @property def config(self): assert len(self.__links__) > 0, "No links provided for fetching" @@ -171,7 +186,8 @@ def _post_init( ) -> None: self._set_units(None, None) self._set_isolated_atom_energies() - self._precompute_statistics(overwrite_local_cache=overwrite_local_cache) + if not self.skip_statistics: + self._precompute_statistics(overwrite_local_cache=overwrite_local_cache) self._set_units(energy_unit, distance_unit) self._convert_data() self._set_isolated_atom_energies() @@ -331,6 +347,10 @@ def convert_forces(self, x): def set_energy_unit(self, value: str): """ Set a new energy unit for the dataset. + + Parameters: + value: + New energy unit to set. """ # old_unit = self.energy_unit # self.__energy_unit__ = value @@ -340,6 +360,10 @@ def set_energy_unit(self, value: str): def set_distance_unit(self, value: str): """ Set a new distance unit for the dataset. + + Parameters: + value: + New distance unit to set. """ # old_unit = self.distance_unit # self.__distance_unit__ = value @@ -351,9 +375,22 @@ def set_array_format(self, format: str): self.array_format = format def read_raw_entries(self): + """ + Preprocess the raw (aka from the fetched source) into a list of dictionaries. + """ raise NotImplementedError - def collate_list(self, list_entries): + def collate_list(self, list_entries: List[Dict]) -> Dict: + """ + Collate a list of entries into a single dictionary. + + Parameters: + list_entries: + List of dictionaries containing the entries to collate. + + Returns: + Dictionary containing the collated entries. + """ # concatenate entries res = {key: np.concatenate([r[key] for r in list_entries if r is not None], axis=0) for key in list_entries[0]} @@ -364,54 +401,29 @@ def collate_list(self, list_entries): return res - def save_preprocess(self, data_dict, upload=False, overwrite=True): + def save_preprocess( + self, data_dict: Dict[str, np.ndarray], upload: bool = False, overwrite: bool = True, as_zarr: bool = False + ): """ Save the preprocessed data to the cache directory and optionally upload it to the remote storage. - data_dict : dict - Dictionary containing the preprocessed data. - upload : bool, Defult: False - Whether to upload the preprocessed data to the remote storage or only saving it locally. - overwrite : bool, Default: False - Whether to overwrite the preprocessed data if it already exists. - Only used if upload is True. Cache is always overwritten locally. + + Parameters: + data_dict: + Dictionary containing the preprocessed data. + upload: + Whether to upload the preprocessed data to the remote storage or only saving it locally. + overwrite: + Whether to overwrite the preprocessed data if it already exists. + Only used if upload is True. Cache is always overwritten locally. """ # save memmaps logger.info("Preprocessing data and saving it to cache.") - for key in self.data_keys: - local_path = p_join(self.preprocess_path, f"{key}.mmap") - out = np.memmap(local_path, mode="w+", dtype=data_dict[key].dtype, shape=data_dict[key].shape) - out[:] = data_dict.pop(key)[:] - out.flush() - if upload: - push_remote(local_path, overwrite=overwrite) - - # save smiles and subset - local_path = p_join(self.preprocess_path, "props.pkl") - - # assert that (required) pkl keys are present in data_dict - assert all([key in data_dict.keys() for key in self.pkl_data_keys]) - - # store unique and inverse indices for str-based pkl keys - for key in self.pkl_data_keys: - if self.pkl_data_types[key] == str: - data_dict[key] = np.unique(data_dict[key], return_inverse=True) - - with open(local_path, "wb") as f: - pkl.dump(data_dict, f) + paths = self.dataset_wrapper.save_preprocess( + self.preprocess_path, self.data_keys, data_dict, self.pkl_data_keys, self.pkl_data_types + ) if upload: - push_remote(local_path, overwrite=overwrite) - - def _convert_on_loading(self, x, key): - if key == "energies": - return self.convert_energy(x) - elif key == "forces": - return self.convert_forces(x) - elif key == "atomic_inputs": - x = np.array(x, dtype=np.float32) - x[:, -3:] = self.convert_distance(x[:, -3:]) - return x - else: - return x + for local_path in paths: + push_remote(local_path, overwrite=overwrite) # make it async? def read_preprocess(self, overwrite_local_cache=False): logger.info("Reading preprocessed data.") @@ -421,62 +433,106 @@ def read_preprocess(self, overwrite_local_cache=False): Distance: {self.distance_unit},\n\ Forces: {self.force_unit if self.force_methods else 'None'}" ) - self.data = {} - for key in self.data_keys: - filename = p_join(self.preprocess_path, f"{key}.mmap") - pull_locally(filename, overwrite=overwrite_local_cache) - self.data[key] = np.memmap(filename, mode="r", dtype=self.data_types[key]).reshape(*self.data_shapes[key]) - - filename = p_join(self.preprocess_path, "props.pkl") - pull_locally(filename, overwrite=overwrite_local_cache) - with open(filename, "rb") as f: - tmp = pkl.load(f) - all_pkl_keys = set(tmp.keys()) - set(self.data_keys) - # assert required pkl_keys are present in all_pkl_keys - assert all([key in all_pkl_keys for key in self.pkl_data_keys]) - for key in all_pkl_keys: - x = tmp.pop(key) - if len(x) == 2: - self.data[key] = x[0][x[1]] - else: - self.data[key] = x + self.data = self.dataset_wrapper.load_data( + self.preprocess_path, + self.data_keys, + self.data_types, + self.data_shapes, + self.pkl_data_keys, + overwrite_local_cache, + ) # this should be async if possible for key in self.data: logger.info(f"Loaded {key} with shape {self.data[key].shape}, dtype {self.data[key].dtype}") - def is_preprocessed(self): + def _convert_on_loading(self, x, key): + if key == "energies": + return self.convert_energy(x) + elif key == "forces": + return self.convert_forces(x) + elif key == "atomic_inputs": + x = np.array(x, dtype=np.float32) + x[:, -3:] = self.convert_distance(x[:, -3:]) + return x + else: + return x + + def is_preprocessed(self) -> bool: """ Check if the dataset is preprocessed and available online or locally. + + Returns: + True if the dataset is available remotely or locally, False otherwise. """ - predicats = [copy_exists(p_join(self.preprocess_path, f"{key}.mmap")) for key in self.data_keys] - predicats += [copy_exists(p_join(self.preprocess_path, "props.pkl"))] + predicats = [ + copy_exists(p_join(self.preprocess_path, self.dataset_wrapper.add_extension(f"{key}"))) + for key in self.data_keys + ] + predicats += [copy_exists(p_join(self.preprocess_path, file)) for file in self.dataset_wrapper._extra_files] return all(predicats) - def is_cached(self): + def is_cached(self) -> bool: """ Check if the dataset is cached locally. + + Returns: + True if the dataset is cached locally, False otherwise. """ - predicats = [os.path.exists(p_join(self.preprocess_path, f"{key}.mmap")) for key in self.data_keys] - predicats += [os.path.exists(p_join(self.preprocess_path, "props.pkl"))] + predicats = [ + os.path.exists(p_join(self.preprocess_path, self.dataset_wrapper.add_extension(f"{key}"))) + for key in self.data_keys + ] + predicats += [copy_exists(p_join(self.preprocess_path, file)) for file in self.dataset_wrapper._extra_files] return all(predicats) - def preprocess(self, upload: bool = False, overwrite: bool = True): + def preprocess(self, upload: bool = False, overwrite: bool = True, as_zarr: bool = True): """ Preprocess the dataset and save it. - upload : bool, Defult: False - Whether to upload the preprocessed data to the remote storage or only saving it locally. - overwrite : bool, Default: False - Whether to overwrite the preprocessed data if it already exists. - Only used if upload is True. Cache is always overwritten locally. + + Parameters: + upload: + Whether to upload the preprocessed data to the remote storage or only saving it locally. + overwrite: + hether to overwrite the preprocessed data if it already exists. + Only used if upload is True. Cache is always overwritten locally. + as_zarr: + Whether to save the data as zarr files """ if overwrite or not self.is_preprocessed(): entries = self.read_raw_entries() res = self.collate_list(entries) - self.save_preprocess(res, upload, overwrite) + self.save_preprocess(res, upload, overwrite, as_zarr) + + def upload(self, overwrite: bool = False, as_zarr: bool = False): + """ + Upload the preprocessed data to the remote storage. Must be called after preprocess and + need to have write privileges. + + Parameters: + overwrite: + Whether to overwrite the remote data if it already exists + as_zarr: + Whether to upload the data as zarr files + """ + for key in self.data_keys: + local_path = p_join(self.preprocess_path, f"{key}.mmap" if not as_zarr else f"{key}.zip") + push_remote(local_path, overwrite=overwrite) + local_path = p_join(self.preprocess_path, "props.pkl" if not as_zarr else "metadata.zip") + push_remote(local_path, overwrite=overwrite) - def save_xyz(self, idx: int, energy_method: int = 0, path: Optional[str] = None, ext=True): + def save_xyz(self, idx: int, energy_method: int = 0, path: Optional[str] = None, ext: bool = True): """ - Save the entry at index idx as an extxyz file. + Save a single entry at index idx as an extxyz file. + + Parameters: + idx: + Index of the entry + energy_method: + Index of the energy method to use + path: + Path to save the xyz file. If None, the current working directory is used. + ext: + Whether to include additional informations like forces and other metadatas (extxyz format) """ if path is None: path = os.getcwd() @@ -486,6 +542,12 @@ def save_xyz(self, idx: int, energy_method: int = 0, path: Optional[str] = None, def to_xyz(self, energy_method: int = 0, path: Optional[str] = None): """ Save dataset as single xyz file (extended xyz format). + + Parameters: + energy_method: + Index of the energy method to use + path: + Path to save the xyz file """ with open(p_join(path if path else os.getcwd(), f"{self.__name__}.xyz"), "w") as f: for atoms in tqdm( @@ -495,16 +557,20 @@ def to_xyz(self, energy_method: int = 0, path: Optional[str] = None): ): write_extxyz(f, atoms, append=True) - def get_ase_atoms(self, idx: int, energy_method: int = 0, ext=True): + def get_ase_atoms(self, idx: int, energy_method: int = 0, ext: bool = True) -> Atoms: """ Get the ASE atoms object for the entry at index idx. - Parameters - ---------- - idx : int - Index of the entry. - ext : bool, optional - Whether to include additional informations + Parameters: + idx: + Index of the entry. + energy_method: + Index of the energy method to use + ext: + Whether to include additional informations + + Returns: + ASE atoms object """ entry = self[idx] at = dict_to_atoms(entry, ext=ext, energy_method=energy_method) @@ -537,24 +603,23 @@ def calculate_descriptors( """ Compute the descriptors for the dataset. - Parameters - ---------- - descriptor_name : str - Name of the descriptor to use. Supported descriptors are ["soap"] - chemical_species : Optional[List[str]], optional - List of chemical species to use for the descriptor computation, by default None. - If None, the chemical species of the dataset are used. - n_samples : Optional[Union[List[int],int, float]], optional - Number of samples to use for the computation, by default None. If None, all the dataset is used. - If a list of integers is provided, the descriptors are computed for each of the specified idx of samples. - progress : bool, optional - Whether to show a progress bar, by default True. - **descriptor_kwargs : dict - Keyword arguments to pass to the descriptor instantiation of the model. - - Returns - ------- - Dict[str, np.ndarray] + Parameters: + descriptor_name: + Name of the descriptor to use. Supported descriptors are ["soap"] + chemical_species: + List of chemical species to use for the descriptor computation, by default None. + If None, the chemical species of the dataset are used. + n_samples: + Number of samples to use for the computation, by default None. + If None, all the dataset is used. + If a list of integers is provided, the descriptors are computed for + each of the specified idx of samples. + progress: + Whether to show a progress bar, by default True. + **descriptor_kwargs : dict + Keyword arguments to pass to the descriptor instantiation of the model. + + Returns: Dictionary containing the following keys: - values : np.ndarray of shape (N, M) containing the descriptors for the dataset - idxs : np.ndarray of shape (N,) containing the indices of the samples used @@ -577,14 +642,18 @@ def wrapper(idx): datum["idxs"] = idxs return datum - def as_iter(self, atoms: bool = False, energy_method: int = 0): + def as_iter(self, atoms: bool = False, energy_method: int = 0) -> Iterable: """ Return the dataset as an iterator. - Parameters - ---------- - atoms : bool, optional - Whether to return the items as ASE atoms object, by default False + Parameters: + atoms: + Whether to return the items as ASE atoms object, by default False + energy_method: + Index of the energy method to use + + Returns: + Iterator of the dataset """ func = partial(self.get_ase_atoms, energy_method=energy_method) if atoms else self.__getitem__ @@ -592,12 +661,21 @@ def as_iter(self, atoms: bool = False, energy_method: int = 0): for i in range(len(self)): yield func(i) - def get_statistics(self, return_none: bool = True): + def __iter__(self): + for idxs in range(len(self)): + yield self[idxs] + + def get_statistics(self, return_none: bool = True) -> Dict: """ Get the converted statistics of the dataset. - return_none : bool, optional - Whether to return None if the statistics for the forces are not available, by default True - Otherwise, the statistics for the forces are set to 0.0 + + Parameters: + return_none : + Whether to return None if the statistics for the forces are not available, by default True + Otherwise, the statistics for the forces are set to 0.0 + + Returns: + Dictionary containing the statistics of the dataset """ selected_stats = self.statistics.get_results() if len(selected_stats) == 0: diff --git a/openqdc/datasets/interaction/des.py b/openqdc/datasets/interaction/des.py index d90be07e..6788c41c 100644 --- a/openqdc/datasets/interaction/des.py +++ b/openqdc/datasets/interaction/des.py @@ -74,13 +74,19 @@ def _create_subsets(self, **kwargs): class DES370K(BaseInteractionDataset, IDES): """ - DE Shaw Research interaction energy of over 370K - small molecule dimers as described in the paper: - - Quantum chemical benchmark databases of gold-standard dimer interaction energies. - Donchev, A.G., Taube, A.G., Decolvenaere, E. et al. - Sci Data 8, 55 (2021). - https://doi.org/10.1038/s41597-021-00833-x + DE Shaw 370K (DES370K) is a dataset of 3,691 distinct dimers with 370K unique geometries with interaction energies + computed at CCSD(T)/CBS level of theory. It consists of 392 closed-shell chemical species (both neutral molecules + and ions) including water and functional groups found in proteins. Dimer geometries are generated using + QM-based optimization with DF-LMP2/aVDZ level of theory and MD-based from condensed phase MD simulations. + + Usage: + ```python + from openqdc.datasets import DES370K + dataset = DES370K() + ``` + + Reference: + https://www.nature.com/articles/s41597-021-00833-x """ __name__ = "des370k_interaction" @@ -173,13 +179,18 @@ def read_raw_entries(self) -> List[Dict]: class DES5M(DES370K): """ - DE Shaw Research interaction energy calculations for - over 5M small molecule dimers as described in the paper: - - Quantum chemical benchmark databases of gold-standard dimer interaction energies. - Donchev, A.G., Taube, A.G., Decolvenaere, E. et al. - Sci Data 8, 55 (2021). - https://doi.org/10.1038/s41597-021-00833-x + DE Shaw 5M (DES5M) is a dataset of 3,691 distinct dimers with 5,000,000 unique geometries with interaction energies + computed using SNS-MP2, a machine learning approach. The unique geometries are generated similar to DES370K using + QM based optimization and MD simulations. + + Usage: + ```python + from openqdc.datasets import DES5M + dataset = DES5M() + ``` + + Reference: + https://www.nature.com/articles/s41597-021-00833-x """ __name__ = "des5m_interaction" @@ -242,18 +253,19 @@ class DES5M(DES370K): class DESS66(DES370K): """ - DE Shaw Research interaction energy - estimates of all 66 conformers from - the original S66 dataset as described - in the paper: - - Quantum chemical benchmark databases of gold-standard dimer interaction energies. - Donchev, A.G., Taube, A.G., Decolvenaere, E. et al. - Sci Data 8, 55 (2021). - https://doi.org/10.1038/s41597-021-00833-x - - Data was downloaded from Zenodo: - https://zenodo.org/records/5676284 + DESS66 is a dataset consisting of 66 molecular complexes from the S66 dataset with CCSD(T)/CBS + dimer interaction energies with 1 equilibrium geometry giving 66 conformers in total. + The protocol for estimating energies is based on the DES370K paper. + + Usage: + ```python + from openqdc.datasets import DESS66 + dataset = DESS66() + ``` + + Reference: + https://www.nature.com/articles/s41597-021-00833-x\n + S66: https://pubs.acs.org/doi/10.1021/ct2002946 """ __name__ = "des_s66" @@ -266,19 +278,18 @@ def _create_subsets(self, **kwargs): class DESS66x8(DESS66): """ - DE Shaw Research interaction energy - estimates of all 528 conformers from - the original S66x8 dataset as described - in the paper: - - Quantum chemical benchmark databases of gold-standard dimer interaction energies. - Donchev, A.G., Taube, A.G., Decolvenaere, E. et al. - Sci Data 8, 55 (2021). - https://doi.org/10.1038/s41597-021-00833-x - - Data was downloaded from Zenodo: - - https://zenodo.org/records/5676284 + DESS66x8 is a dataset consisting of 66 molecular complexes from the S66 dataset with CCSD(T)/CBS + dimer interaction energies with 1 equilibrium geometry and 8 geometries along the dissociation curve + giving 592 conformers in total. The protocol for estimating energies is based on the DES370K paper. + + Usage: + ```python + from openqdc.datasets import DESS66x8 + dataset = DESS66x8() + ``` + + Reference: + https://www.nature.com/articles/s41597-021-00833-x """ __name__ = "des_s66x8" diff --git a/openqdc/datasets/interaction/l7.py b/openqdc/datasets/interaction/l7.py index 75a63cd5..7307638c 100644 --- a/openqdc/datasets/interaction/l7.py +++ b/openqdc/datasets/interaction/l7.py @@ -7,15 +7,18 @@ class L7(YamlDataset): """ - The L7 interaction energy dataset as described in: - - Accuracy of Quantum Chemical Methods for Large Noncovalent Complexes - Robert Sedlak, Tomasz Janowski, Michal Pitoňák, Jan Řezáč, Peter Pulay, and Pavel Hobza - Journal of Chemical Theory and Computation 2013 9 (8), 3364-3374 - DOI: 10.1021/ct400036b - - Data was downloaded and extracted from: - http://cuby4.molecular.cz/dataset_l7.html + The L7 interaction energy dataset consists of 7 dispersion stabilized non-covalent complexes with + energies labelled using semi-empirical and quantum mechanical methods. The intial geometries are + taken from crystal X-ray data and optimized with a DFT method specific to the complex. + + Usage: + ```python + from openqdc.datasets import L7 + dataset = L7() + ``` + + Reference: + https://pubs.acs.org/doi/10.1021/ct400036b """ __name__ = "l7" diff --git a/openqdc/datasets/interaction/metcalf.py b/openqdc/datasets/interaction/metcalf.py index faf5324f..889370e8 100644 --- a/openqdc/datasets/interaction/metcalf.py +++ b/openqdc/datasets/interaction/metcalf.py @@ -84,20 +84,19 @@ def read_xyz(fname, subset): class Metcalf(BaseInteractionDataset): """ - Hydrogen-bonded dimers of NMA with 126 molecules as described in: - - Approaches for machine learning intermolecular interaction energies and - application to energy components from symmetry adapted perturbation theory. - Derek P. Metcalf, Alexios Koutsoukas, Steven A. Spronk, Brian L. Claus, - Deborah A. Loughney, Stephen R. Johnson, Daniel L. Cheney, C. David Sherrill; - J. Chem. Phys. 21 February 2020; 152 (7): 074103. - https://doi.org/10.1063/1.5142636 - - Further details: - "Hydrogen-bonded dimers involving N-methylacetamide (NMA) and 126 molecules - (46 donors and 80 acceptors; Figs. 2 and 3) were used. Optimized geometries - for the 126 individual monomers were obtained and paired with NMA in broad - arrays of spatial configurations to generate thousands of complexes for training. + Metcalf is a dataset consisting of 126 hydrogen-bonded dimers involving N-methylacetamide (NMA) with 14,744 to + 156,704 geometries/configurations for each complex. The geometries are optimized using the RI-MP2 method and + the cc-pVTZ basis set. SAPT(0) calculations are performed for computing interaction energies and the various + components. + + Usage: + ```python + from openqdc.datasets import Metcalf + dataset = Metcalf() + ``` + + Reference: + https://doi.org/10.1063/1.5142636 """ __name__ = "metcalf" diff --git a/openqdc/datasets/interaction/splinter.py b/openqdc/datasets/interaction/splinter.py index bda10129..6ba3b4d5 100644 --- a/openqdc/datasets/interaction/splinter.py +++ b/openqdc/datasets/interaction/splinter.py @@ -12,13 +12,18 @@ class Splinter(BaseInteractionDataset): """ - A dataset of over 1.7 million protein-ligand - interactions as described in the paper: + Splinter consists of 30,416A dimer pairs with over 1.5 million geometries. The geometries are generated + by quantum mechanical optimization with B3LYP-D3/aug-cc-pV(D+d)Z level of theory. The interaction energies + and the various components are computed using SAPT0/qug-cc-pV(D=d)Z method. - A quantum chemical interaction energy dataset for accurately modeling protein-ligand interactions. - Spronk, S.A., Glick, Z.L., Metcalf, D.P. et al. - Sci Data 10, 619 (2023). - https://doi.org/10.1038/s41597-023-02443-1 + Usage: + ```python + from openqdc.datasets import Splinter + dataset = Splinter() + ``` + + Reference: + https://doi.org/10.1038/s41597-023-02443-1 """ __energy_unit__ = "kcal/mol" diff --git a/openqdc/datasets/interaction/x40.py b/openqdc/datasets/interaction/x40.py index 64da5d87..d56a976d 100644 --- a/openqdc/datasets/interaction/x40.py +++ b/openqdc/datasets/interaction/x40.py @@ -8,16 +8,21 @@ class X40(YamlDataset): """ - X40 interaction dataset of 40 dimer pairs as - introduced in the following paper: - - Benchmark Calculations of Noncovalent Interactions of Halogenated Molecules - Jan Řezáč, Kevin E. Riley, and Pavel Hobza - Journal of Chemical Theory and Computation 2012 8 (11), 4285-4292 - DOI: 10.1021/ct300647k - - Dataset retrieved and processed from: - http://cuby4.molecular.cz/dataset_x40.html + X40 interaction dataset of 40 noncovalent complexes of organic halides, halohydrides, and halogen molecules + where the halogens participate in various interaction types such as electrostatic interactions, london + dispersion, hydrogen bonds, halogen bonding, halogen-pi interactions and stacking of halogenated aromatic + molecules. For each complex 10 geometries are generated resulting in 400 geometries in the dataset. The geometries + are optimized using the MP2 level of theory with cc-pVTZ basis set whereas the interaction energies are + computed with CCSD(T)/CBS level of theory. + + Usage: + ```python + from openqdc.datasets import X40 + dataset = X40() + ``` + + Reference: + https://pubs.acs.org/doi/10.1021/ct300647k """ __name__ = "x40" diff --git a/openqdc/datasets/io.py b/openqdc/datasets/io.py index 1e621f72..7316768b 100644 --- a/openqdc/datasets/io.py +++ b/openqdc/datasets/io.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Callable, List, Optional +from typing import Callable, Dict, List, Optional import datamol as dm import numpy as np @@ -17,6 +17,8 @@ def try_retrieve(obj, callable, default=None): class FromFileDataset(BaseDataset, ABC): + """Abstract class for datasets that read from a common format file like xzy, netcdf, gro, hdf5, etc.""" + def __init__( self, path: List[str], @@ -28,6 +30,7 @@ def __init__( array_format: Optional[str] = "numpy", level_of_theory: Optional[QmMethod] = None, transform: Optional[Callable] = None, + skip_statistics: bool = False, regressor_kwargs={ "solver_type": "linear", "sub_sample": None, @@ -35,18 +38,37 @@ def __init__( }, ): """ - Create a dataset from a xyz file. + Create a dataset from a list of files. Parameters ---------- path : List[str] The path to the file or a list of paths. + dataset_name : Optional[str], optional + The name of the dataset, by default None. + energy_type : Optional[str], optional + The type of isolated atom energy by default "regression". + Supported types: ["formation", "regression", "null", None] + energy_unit + Energy unit of the dataset. Default is "hartree". + distance_unit + Distance unit of the dataset. Default is "ang". + level_of_theory: Optional[QmMethod, str] + The level of theory of the dataset. + Used if energy_type is "formation" to fetch the correct isolated atom energies. + transform, optional + transformation to apply to the __getitem__ calls + regressor_kwargs + Dictionary of keyword arguments to pass to the regressor. + Default: {"solver_type": "linear", "sub_sample": None, "stride": 1} + solver_type can be one of ["linear", "ridge"] """ self.path = [path] if isinstance(path, str) else path self.__name__ = self.__class__.__name__ if dataset_name is None else dataset_name self.recompute_statistics = True self.refit_e0s = True self.energy_type = energy_type + self.skip_statistics = skip_statistics self.__energy_unit__ = energy_unit self._original_unit = self.energy_unit self.__distance_unit__ = distance_unit @@ -62,29 +84,19 @@ def __init__( self.set_array_format(array_format) self._post_init(True, energy_unit, distance_unit) - def __str__(self): - return self.__name__.lower() - - def __repr__(self): - return str(self) - @abstractmethod def read_as_atoms(self, path: str) -> List[Atoms]: """ - Method that reads a path and return a list of Atoms objects. + Method that reads a file and return a list of Atoms objects. + path : str + The path to the file. """ raise NotImplementedError - def collate_list(self, list_entries): - res = {key: np.concatenate([r[key] for r in list_entries if r is not None], axis=0) for key in list_entries[0]} - csum = np.cumsum(res.get("n_atoms")) - x = np.zeros((csum.shape[0], 2), dtype=np.int32) - x[1:, 0], x[:, 1] = csum[:-1], csum - res["position_idx_range"] = x - - return res - - def read_raw_entries(self): + def read_raw_entries(self) -> List[Dict]: + """ + Process the files and return a list of data objects. + """ entries_list = [] for path in self.path: for entry in self.read_as_atoms(path): @@ -96,6 +108,11 @@ def _read_and_preprocess(self): self.data = self.collate_list(entries_list) def _convert_to_record(self, obj: Atoms): + """ + Convert an Atoms object to a record for the openQDC dataset processing. + obj : Atoms + The ase.Atoms object to convert + """ name = obj.info.get("name", None) subset = obj.info.get("subset", str(self)) positions = obj.positions @@ -116,8 +133,18 @@ def _convert_to_record(self, obj: Atoms): n_atoms=np.array([len(positions)], dtype=np.int32), ) + def __str__(self): + return self.__name__.lower() + + def __repr__(self): + return str(self) + class XYZDataset(FromFileDataset): + """ + Baseclass to read datasets from xyz and extxyz files. + """ + def read_as_atoms(self, path): from ase.io import iread diff --git a/openqdc/datasets/potential/__init__.py b/openqdc/datasets/potential/__init__.py index b59fcad7..35721dde 100644 --- a/openqdc/datasets/potential/__init__.py +++ b/openqdc/datasets/potential/__init__.py @@ -1,6 +1,7 @@ +from .alchemy import Alchemy from .ani import ANI1, ANI1CCX, ANI1CCX_V2, ANI1X, ANI2X from .comp6 import COMP6 -from .dummy import Dummy +from .dummy import Dummy, PredefinedDataset from .gdml import GDML from .geom import GEOM from .iso_17 import ISO17 @@ -10,18 +11,23 @@ from .nabladft import NablaDFT from .orbnet_denali import OrbnetDenali from .pcqm import PCQM_B3LYP, PCQM_PM6 +from .proteinfragments import MDDataset, ProteinFragments from .qm1b import QM1B, QM1B_SMALL from .qm7x import QM7X, QM7X_V2 from .qmugs import QMugs, QMugs_V2 +from .qmx import QM7, QM8, QM9, QM7b from .revmd17 import RevMD17 from .sn2_rxn import SN2RXN from .solvated_peptides import SolvatedPeptides from .spice import Spice, SpiceV2, SpiceVL2 from .tmqm import TMQM from .transition1x import Transition1X +from .vqm24 import VQM24 +from .waterclusters import SCANWaterClusters from .waterclusters3_30 import WaterClusters AVAILABLE_POTENTIAL_DATASETS = { + "Alchemy": Alchemy, "ANI1": ANI1, "ANI1CCX": ANI1CCX, "ANI1CCX_V2": ANI1CCX_V2, @@ -42,6 +48,10 @@ "QMugs_V2": QMugs_V2, "QM1B": QM1B, "QM1B_SMALL": QM1B_SMALL, + "QM7": QM7, + "QM7b": QM7b, + "QM8": QM8, + "QM9": QM9, "SN2RXN": SN2RXN, "SolvatedPeptides": SolvatedPeptides, "Spice": Spice, @@ -50,8 +60,12 @@ "TMQM": TMQM, "Transition1X": Transition1X, "WaterClusters": WaterClusters, + "SCANWaterClusters": SCANWaterClusters, "MultixcQM9": MultixcQM9, "MultixcQM9_V2": MultixcQM9_V2, "RevMD17": RevMD17, "MD22": MD22, + "VQM24": VQM24, + "ProteinFragments": ProteinFragments, + "MDDataset": MDDataset, } diff --git a/openqdc/datasets/potential/alchemy.py b/openqdc/datasets/potential/alchemy.py new file mode 100644 index 00000000..24c17cd9 --- /dev/null +++ b/openqdc/datasets/potential/alchemy.py @@ -0,0 +1,95 @@ +from os.path import join as p_join + +import datamol as dm +import numpy as np +import pandas as pd +from tqdm import tqdm + +from openqdc.datasets.base import BaseDataset +from openqdc.methods import PotentialMethod +from openqdc.utils.molecule import get_atomic_number_and_charge + +# ['gdb_idx', 'atom number', 'zpve\n(Ha, zero point vibrational energy)', +#'Cv\n(cal/molK, heat capacity at 298.15 K)', 'gap\n(Ha, LUMO-HOMO)', +# 'G\n(Ha, Free energy at 298.15 K)', 'HOMO\n(Ha, energy of HOMO)', +# 'U\n(Ha, internal energy at 298.15 K)', 'alpha\n(a_0^3, Isotropic polarizability)', +# 'U0\n(Ha, internal energy at 0 K)', 'H\n(Ha, enthalpy at 298.15 K)', +# 'LUMO\n(Ha, energy of LUMO)', 'mu\n(D, dipole moment)', +# 'R2\n(a_0^2, electronic spatial extent)'] + + +def read_mol(file, energy): + try: + mol = dm.read_sdf(file, remove_hs=False)[0] + positions = mol.GetConformer().GetPositions() + x = get_atomic_number_and_charge(mol) + n_atoms = positions.shape[0] + res = dict( + atomic_inputs=np.concatenate((x, positions), axis=-1, dtype=np.float32).reshape(-1, 5), + name=np.array([dm.to_smiles(mol)]), + energies=np.array([energy], dtype=np.float64)[:, None], + n_atoms=np.array([n_atoms], dtype=np.int32), + subset=np.array([f"atoms_{n_atoms}"]), + ) + + except Exception as e: + print(f"Skipping due to {e}") + res = None + + return res + + +# e B3LYP/6-31G(2df,p) model with the density fitting +# approximation for electron repulsion integrals. The auxiliary basis cc-pVDZ-jkf + + +class Alchemy(BaseDataset): + """ + Alchemy comprises of 119,487 organic molecules with up to 14 heavy atoms, sampled from the GDB MedChem database. + Molecular properties are calculated using PySCF's implementation of the DFT Kohn-Sham method at the B3LYP level + with the basis set 6-31G(2df,p). The equilibrium geometry is optimized in three passes. First, OpenBabel is used + to parse SMILES string and build the Cartesian coordinates with MMFF94 force field optimization. Second, HF/STO3G + is used to generate the preliminary geometry. Third, for the final pass of geometry relaxation, the + B3LYP/6-31G(2df,p) model with the density fittting approximation for electron repulsion integrals is used. The + auxillary basis cc-pVDZ-jkfit is employed in density fitting to build the Coulomb matrix and the HF exchange + matrix. + + Usage: + ```python + from openqdc.datasets import Alchemy + dataset = Alchemy() + ``` + + Reference: + https://arxiv.org/abs/1906.09427 + https://alchemy.tencent.com/ + """ + + __name__ = "alchemy" + + __energy_methods__ = [ + PotentialMethod.WB97X_6_31G_D, # "wb97x/6-31g(d)" + ] + + energy_target_names = [ + "ωB97x:6-31G(d) Energy", + ] + + __energy_unit__ = "hartree" + __distance_unit__ = "ang" + __forces_unit__ = "hartree/ang" + __links__ = {"alchemy.zip": "https://alchemy.tencent.com/data/alchemy-v20191129.zip"} + + def read_raw_entries(self): + dir_path = p_join(self.root, "Alchemy-v20191129") + full_csv = pd.read_csv(p_join(dir_path, "final_version.csv")) + energies = full_csv["U0\n(Ha, internal energy at 0 K)"].tolist() + atom_folder = full_csv["atom number"] + gdb_idx = full_csv["gdb_idx"] + idxs = full_csv.index.tolist() + samples = [] + for i in tqdm(idxs): + sdf_file = p_join(dir_path, f"atom_{atom_folder[i]}", f"{gdb_idx[i]}.sdf") + energy = energies[i] + samples.append(read_mol(sdf_file, energy)) + return samples diff --git a/openqdc/datasets/potential/ani.py b/openqdc/datasets/potential/ani.py index bcff384f..aac35635 100644 --- a/openqdc/datasets/potential/ani.py +++ b/openqdc/datasets/potential/ani.py @@ -39,19 +39,22 @@ def extract_ani2_entries(properties): class ANI1(BaseDataset): """ - The ANI-1 dataset is a collection of 22 x 10^6 structural conformations from 57,000 distinct small - organic molecules with energy labels calculated using DFT. The molecules - contain 4 distinct atoms, C, N, O and H. - - Usage + The ANI-1 dataset is a collection of 22 x 10^6 structural conformations from 57,000 distinct small organic + molecules. The molecules contain 4 distinct atoms, C, N, O and H. Electronic structure calculations use the + wB97x density functional and the 6-31G(d) basis set. For generating structures, smiles strings for molecules + are used for generating 3D conformations using RDKit. These 3D structures are then pre-optimized to a stationary + point using the MMFF94 force field. Finally, geometries are optimized until energy minima using the chosen DFT + level. + + Usage: ```python from openqdc.datasets import ANI1 dataset = ANI1() ``` References: - - ANI-1: https://www.nature.com/articles/sdata2017193 - - Github: https://github.com/aiqm/ANI1x_datasets + https://www.nature.com/articles/sdata2017193\n + https://github.com/aiqm/ANI1x_datasets """ __name__ = "ani1" @@ -79,9 +82,6 @@ def config(self): return dict(dataset_name="ani", links=self.__links__) def __smiles_converter__(self, x): - """util function to convert string to smiles: useful if the smiles is - encoded in a different format than its display format - """ return "-".join(x.decode("ascii").split("-")[:-1]) @property @@ -96,64 +96,23 @@ def read_raw_entries(self): return samples -class ANI1CCX(ANI1): - """ - ANI1-CCX is a dataset of 500k conformers subsampled from the 5.5M conformers of ANI-1X dataset. The selected - conformations are then labelled using a high accuracy CCSD(T)*/CBS method. - - Usage - ```python - from openqdc.datasets import ANI1CCX - dataset = ANI1CCX() - ``` - - References: - - ANI-1ccx: https://doi.org/10.1038/s41467-019-10827-4 - - Github: https://github.com/aiqm/ANI1x_datasets - """ - - __name__ = "ani1ccx" - __energy_unit__ = "hartree" - __distance_unit__ = "ang" - __forces_unit__ = "hartree/ang" - - __energy_methods__ = [ - PotentialMethod.NONE, # "ccsd(t)/cbs", - PotentialMethod.NONE, # "ccsd(t)/cc-pvdz", - PotentialMethod.NONE, # "ccsd(t)/cc-pvtz", - PotentialMethod.NONE, # "tccsd(t)/cc-pvdz", - ] - - energy_target_names = [ - "CCSD(T)*:CBS Total Energy", - "NPNO-CCSD(T):cc-pVDZ Correlation Energy", - "NPNO-CCSD(T):cc-pVTZ Correlation Energy", - "TPNO-CCSD(T):cc-pVDZ Correlation Energy", - ] - force_target_names = [] - __links__ = {"ani1x.hdf5.gz": "https://zenodo.org/record/4081694/files/292.hdf5.gz"} - - def __smiles_converter__(self, x): - """util function to convert string to smiles: useful if the smiles is - encoded in a different format than its display format - """ - return x - - class ANI1X(ANI1): """ The ANI-1X dataset consists of ANI-1 molecules + some molecules added using active learning, which leads to - a total of 5,496,771 conformers with 63,865 unique molecules. + a total of 5,496,771 conformers with 63,865 unique molecules. Databases of molecules like GDB-11, ChEMBL, + generated amino acids and 2-amino acid peptides are used for sampling new molecules. One of the techniques + are used for sampling conformations, (1) molecular dynamics, (2) normal mode sampling, (3) dimer sampling and + (4) torsion sampling. - Usage + Usage: ```python from openqdc.datasets import ANI1X dataset = ANI1X() ``` References: - - ANI-1x: https://doi.org/10.1063/1.5023802 - - Github: https://github.com/aiqm/ANI1x_datasets + https://doi.org/10.1063/1.5023802\n + https://github.com/aiqm/ANI1x_datasets """ __name__ = "ani1x" @@ -162,14 +121,14 @@ class ANI1X(ANI1): __forces_unit__ = "hartree/ang" __energy_methods__ = [ - "hf/cc-pvdz", - "hf/cc-pvqz", - "hf/cc-pvtz", - "mp2/cc-pvdz", - "mp2/cc-pvqz", - "mp2/cc-pvtz", - "wb97x/6-31g(d)", - "wb97x/cc-pvtz", + PotentialMethod.NONE, # "hf/cc-pvdz", + PotentialMethod.NONE, # "hf/cc-pvqz", + PotentialMethod.NONE, # "hf/cc-pvtz", + PotentialMethod.NONE, # "mp2/cc-pvdz", + PotentialMethod.NONE, # "mp2/cc-pvqz", + PotentialMethod.NONE, # "mp2/cc-pvtz", + PotentialMethod.NONE, # "wb97x/6-31g(d)", + PotentialMethod.NONE, # "wb97x/cc-pvtz", ] energy_target_names = [ @@ -194,6 +153,47 @@ class ANI1X(ANI1): def convert_forces(self, x): return super().convert_forces(x) * 0.529177249 # correct the Dataset error + def __smiles_converter__(self, x): + return x + + +class ANI1CCX(ANI1): + """ + ANI1-CCX is a dataset of 500k conformers subsampled from the 5.5M conformers of ANI-1X dataset using active + learning. The conformations are labelled using a high accuracy CCSD(T)*/CBS method. + + Usage: + ```python + from openqdc.datasets import ANI1CCX + dataset = ANI1CCX() + ``` + + References: + https://doi.org/10.1038/s41467-019-10827-4\n + https://github.com/aiqm/ANI1x_datasets + """ + + __name__ = "ani1ccx" + __energy_unit__ = "hartree" + __distance_unit__ = "ang" + __forces_unit__ = "hartree/ang" + + __energy_methods__ = [ + PotentialMethod.NONE, # "ccsd(t)/cbs", + PotentialMethod.NONE, # "ccsd(t)/cc-pvdz", + PotentialMethod.NONE, # "ccsd(t)/cc-pvtz", + PotentialMethod.NONE, # "tccsd(t)/cc-pvdz", + ] + + energy_target_names = [ + "CCSD(T)*:CBS Total Energy", + "NPNO-CCSD(T):cc-pVDZ Correlation Energy", + "NPNO-CCSD(T):cc-pVTZ Correlation Energy", + "TPNO-CCSD(T):cc-pVDZ Correlation Energy", + ] + force_target_names = [] + __links__ = {"ani1x.hdf5.gz": "https://zenodo.org/record/4081694/files/292.hdf5.gz"} + def __smiles_converter__(self, x): """util function to convert string to smiles: useful if the smiles is encoded in a different format than its display format @@ -202,6 +202,21 @@ def __smiles_converter__(self, x): class ANI1CCX_V2(ANI1CCX): + """ + ANI1CCX_V2 is an extension of the ANI1CCX dataset with additional PM6 and GFN2_xTB labels + for each conformation. + + Usage: + ```python + from openqdc.datasets import ANI1CCX_V2 + dataset = ANI1CCX_V2() + ``` + + References: + https://doi.org/10.1038/s41467-019-10827-4\n + https://github.com/aiqm/ANI1x_datasets + """ + __name__ = "ani1ccx_v2" __energy_methods__ = ANI1CCX.__energy_methods__ + [PotentialMethod.PM6, PotentialMethod.GFN2_XTB] @@ -211,19 +226,20 @@ class ANI1CCX_V2(ANI1CCX): class ANI2X(ANI1): """ - The ANI-2X dataset was constructed using active learning from modified versions of GDB-11, CheMBL, - and s66x8. It adds three new elements (F, Cl, S) resulting in 4.6 million conformers from 13k - chemical isomers, optimized using the LBFGS algorithm and labeled with ωB97X/6-31G*. + The ANI-2X dataset was constructed using active learning from modified versions of GDB-11, CheMBL, and s66x8. + It adds three new elements (F, Cl, S) resulting in 4.6 million conformers from 13k chemical isomers, optimized + using the LBFGS algorithm and labeled with ωB97X/6-31G*. The same sampling techniques as done in ANI-1X are + used for generating geometries. - Usage + Usage: ```python - from openqdc.datasets import ANI@X + from openqdc.datasets import ANI2X dataset = ANI2X() ``` References: - - ANI-2x: https://doi.org/10.1021/acs.jctc.0c00121 - - Github: https://github.com/aiqm/ANI1x_datasets + https://doi.org/10.1021/acs.jctc.0c00121 + https://github.com/aiqm/ANI1x_datasets """ __name__ = "ani2x" @@ -258,9 +274,6 @@ class ANI2X(ANI1): } def __smiles_converter__(self, x): - """util function to convert string to smiles: useful if the smiles is - encoded in a different format than its display format - """ return x def read_raw_entries(self): diff --git a/openqdc/datasets/potential/comp6.py b/openqdc/datasets/potential/comp6.py index d5998e0a..fe24825c 100644 --- a/openqdc/datasets/potential/comp6.py +++ b/openqdc/datasets/potential/comp6.py @@ -7,19 +7,43 @@ class COMP6(BaseDataset): """ - COMP6 is a benchmark suite consisting of broad regions of bio-chemical and organic space - developed for testing the ANI-1x potential. It is curated from 6 benchmark sets: - S66x8, ANI Molecular Dynamics, GDB7to9, GDB10to13, DrugBank, and Tripeptides. + COMP6 is a benchmark suite consisting of broad regions of bio-chemical and organic space developed for testing the + ANI-1x potential. It is curated from 6 benchmark sets: S66x8, ANI-MD, GDB7to9, GDB10to13, DrugBank, and + Tripeptides. Energies and forces for all non-equilibrium molecular conformations are calculated using + the wB97x density functional with the 6-31G(d) basis set. The dataset also includes Hirshfield charges and + molecular dipoles. - Usage + Details of the benchmark sets are as follows: + S66x8: Consists of 66 dimeric systems involving hydrogen bonding, pi-pi stacking, London interactions and + mixed influence interactions.\n + ANI Molecular Dynamics (ANI-MD): Forces from the ANI-1x potential are used for running 1ns vacuum molecular + dynamics with a 0.25fs time step at 300K using the Langevin thermostat of 14 well-known drug molecules and 2 small + proteins. A random subsample of 128 frames from each 1ns trajectory is selected, and reference DFT single point + calculations are performed to calculate energies and forces.\n + GDB7to9: Consists of 1500 molecules where 500 per 7, 8 and 9 heavy atoms subsampled from the GDB-11 dataset. + The intial structure are randomly embedded into 3D space using RDKit and are optimized with tight convergence + criteria. Normal modes/force constants are computer using the reference DFT model. Finally, Diverse normal + mode sampling (DNMS) is carried out to generate non-equilibrium conformations.\n + GDB10to13: Consists of 3000 molecules where 500 molecules per 10 and 11 heavy atoms are subsampled from GDB-11 + and 1000 molecules per 12 and 13 heavy atom are subsampled from GDB-13. Non-equilibrium conformations are + generated via DNMS.\n + Tripeptide: Consists of 248 random tripeptides. Structures are optimized similar to GDB7to9.\n + DrugBank: Consists of 837 molecules subsampled from the original DrugBank database of real drug molecules. + Structures are optimized similar to GDB7to9. + + Usage: ```python from openqdc.datasets import COMP6 dataset = COMP6() ``` References: - - https://aip.scitation.org/doi/abs/10.1063/1.5023802 - - Github: https://github.com/isayev/COMP6 + https://aip.scitation.org/doi/abs/10.1063/1.5023802\n + https://github.com/isayev/COMP6\n + S66x8: https://pubs.rsc.org/en/content/articlehtml/2016/cp/c6cp00688d\n + GDB-11: https://pubmed.ncbi.nlm.nih.gov/15674983/\n + GDB-13: https://pubmed.ncbi.nlm.nih.gov/19505099/\n + DrugBank: https://pubs.acs.org/doi/10.1021/ja902302h """ __name__ = "comp6" diff --git a/openqdc/datasets/potential/gdml.py b/openqdc/datasets/potential/gdml.py index 24f283e6..24c74754 100644 --- a/openqdc/datasets/potential/gdml.py +++ b/openqdc/datasets/potential/gdml.py @@ -8,25 +8,32 @@ class GDML(BaseDataset): """ Gradient Domain Machine Learning (GDML) is a dataset consisting of samples from ab initio - molecular dynamics (AIMD) trajectories. The dataset consists of, - - Benzene: 627000 samples - - Uracil: 133000 samples - - Naptalene: 326000 samples - - Aspirin: 211000 samples - - Salicylic Acid: 320000 samples - - Malonaldehyde: 993000 samples - - Ethanol: 555000 samples - - Toluene: 100000 samples + molecular dynamics (AIMD) trajectories at a resolution of 0.5fs. The dataset consists of, Benzene + (627000 conformations), Uracil (133000 conformations), Naptalene (326000 conformations), Aspirin + (211000 conformations) Salicylic Acid (320000 conformations), Malonaldehyde (993000 conformations), + Ethanol (555000 conformations) and Toluene (100000 conformations). Energy and force labels for + each conformation are computed using the PBE + vdW-TS electronic structure method. + molecular dynamics (AIMD) trajectories. - Usage + The dataset consists of the following trajectories: + Benzene: 627000 samples\n + Uracil: 133000 samples\n + Naptalene: 326000 samples\n + Aspirin: 211000 samples\n + Salicylic Acid: 320000 samples\n + Malonaldehyde: 993000 samples\n + Ethanol: 555000 samples\n + Toluene: 100000 samples\n + + Usage: ```python from openqdc.datasets import GDML dataset = GDML() ``` References: - - https://www.science.org/doi/10.1126/sciadv.1603015 - - http://www.sgdml.org/#datasets + https://www.science.org/doi/10.1126/sciadv.1603015 + http://www.sgdml.org/#datasets """ __name__ = "gdml" diff --git a/openqdc/datasets/potential/geom.py b/openqdc/datasets/potential/geom.py index d07a3d93..7c86b1e3 100644 --- a/openqdc/datasets/potential/geom.py +++ b/openqdc/datasets/potential/geom.py @@ -61,9 +61,11 @@ def read_mol(mol_id: str, mol_dict, base_path: str, partition: str) -> Dict[str, class GEOM(BaseDataset): """ - The Geometric Ensemble Of Molecules (GEOM) dataset contains 37 million conformers for 133,000 molecules - from QM9, and 317,000 molecules with experimental data related to biophysics, physiology, - and physical chemistry. The dataset is generated using the GFN2-xTB semi-empirical method. + Geometric Ensemble Of Molecules (GEOM) dataset contains 37 million conformers for 133,000 molecules + from QM9, and 317,000 molecules with experimental data related to biophysics, physiology, and physical chemistry. + For each molecule, the initial structure is generated with RDKit, optimized with the GFN2-xTB energy method and + the lowest energy conformer is fed to the CREST software. CREST software uses metadynamics for exploring the + conformational space for each molecule. Energies in the dataset are computed using semi-empirical method GFN2-xTB. Usage: ```python @@ -72,8 +74,9 @@ class GEOM(BaseDataset): ``` References: - - https://www.nature.com/articles/s41597-022-01288-4 - - https://github.com/learningmatter-mit/geom + https://www.nature.com/articles/s41597-022-01288-4\n + https://github.com/learningmatter-mit/geom\n + CREST Software: https://pubs.rsc.org/en/content/articlelanding/2020/cp/c9cp06869d """ __name__ = "geom" diff --git a/openqdc/datasets/potential/iso_17.py b/openqdc/datasets/potential/iso_17.py index fe6aab5c..5672650b 100644 --- a/openqdc/datasets/potential/iso_17.py +++ b/openqdc/datasets/potential/iso_17.py @@ -7,11 +7,12 @@ class ISO17(BaseDataset): """ - ISO17 dataset consists of the largest set of isomers from the QM9 dataset that consists of a fixed - composition of atoms (C7O2H10) arranged in different chemically valid structures. It consist - of 129 molecules, each containing 5,000 conformational geometries, energies and forces with a resolution - of 1 femtosecond in the molecular dynamics trajectories. The simulations were carried out using the - Perdew-Burke-Ernzerhof (PBE) functional and the Tkatchenko-Scheffler (TS) van der Waals correction method. + ISO17 dataset consists of the largest set of isomers from the QM9 dataset that consists of a fixed composition of + atoms (C7O2H10) arranged in different chemically valid structures. It consist of 129 molecules, each containing + 5,000 conformational geometries, energies and forces with a resolution of 1 fs in the molecular dynamics + trajectories. The simulations were carried out using density functional theory (DFT) in the generalized gradient + approximation (GGA) with the Perdew-Burke-Ernzerhof (PBE) functional and the Tkatchenko-Scheffler (TS) van der + Waals correction method. Usage: ```python @@ -20,7 +21,11 @@ class ISO17(BaseDataset): ``` References: - - https://paperswithcode.com/dataset/iso17 + https://arxiv.org/abs/1706.08566\n + https://arxiv.org/abs/1609.08259\n + https://www.nature.com/articles/sdata201422\n + https://pubmed.ncbi.nlm.nih.gov/10062328/\n + https://pubmed.ncbi.nlm.nih.gov/19257665/ """ __name__ = "iso_17" diff --git a/openqdc/datasets/potential/md22.py b/openqdc/datasets/potential/md22.py index b9976426..0eb4a72c 100644 --- a/openqdc/datasets/potential/md22.py +++ b/openqdc/datasets/potential/md22.py @@ -40,6 +40,22 @@ def create_path(filename, root): class MD22(RevMD17): + """ + MD22 consists of molecular dynamics (MD) trajectories of four major classes of biomolecules and supramolecules, + ranging from a small peptide with 42 atoms to a double-walled nanotube with 370 atoms. The simulation trajectories + are sampled at 400K and 500K with a resolution of 1fs. Potential energy and forces are computed using the PBE+MBD + level of theory. + + Usage: + ```python + from openqdc.datasets import MD22 + dataset = MD22() + ``` + + Reference: + https://arxiv.org/abs/2209.14865 + """ + __name__ = "md22" __links__ = { f"{x}.npz": f"http://www.quantum-machine.org/gdml/repo/datasets/md22_{x}.npz" diff --git a/openqdc/datasets/potential/molecule3d.py b/openqdc/datasets/potential/molecule3d.py index ec1dbd00..fa4f4683 100644 --- a/openqdc/datasets/potential/molecule3d.py +++ b/openqdc/datasets/potential/molecule3d.py @@ -67,9 +67,10 @@ def _read_sdf(sdf_path: str, properties_path: str) -> List[Dict[str, np.ndarray] class Molecule3D(BaseDataset): """ - Molecule3D dataset consists of 3,899,647 molecules with ground state geometries and energies - calculated at the B3LYP/6-31G* level of theory. The molecules are extracted from the - PubChem database and cleaned by removing invalid molecule files. + Molecule3D dataset consists of 3,899,647 molecules with equilibrium geometries and energies calculated at the + B3LYP/6-31G* level of theory. The molecules are extracted from the PubChem database and cleaned by removing + molecules with invalid molecule files, with SMILES conversion error, RDKIT warnings, sanitization problems, + or with damaged log files. Usage: ```python @@ -78,8 +79,8 @@ class Molecule3D(BaseDataset): ``` References: - - https://arxiv.org/abs/2110.01717 - - https://github.com/divelab/MoleculeX + https://arxiv.org/abs/2110.01717\n + https://github.com/divelab/MoleculeX """ __name__ = "molecule3d" diff --git a/openqdc/datasets/potential/multixcqm9.py b/openqdc/datasets/potential/multixcqm9.py index 70dab1ea..41d7a4dc 100644 --- a/openqdc/datasets/potential/multixcqm9.py +++ b/openqdc/datasets/potential/multixcqm9.py @@ -37,20 +37,21 @@ def read_xyz_files(folder_path): class MultixcQM9(BaseDataset): """ - MultixcQM9 is a dataset of molecular and reaction energies from - multi-level quantum chemical methods consisting of 133 K QM9 molecules - calculated with 76 different DFT functionals and three different basis sets - (228 energy numbers for each molecule) + 1 GFN2-XTB calculation. + MultixcQM9 is a dataset of molecular and reaction energies from multi-level quantum chemical methods consisting + of 133K QM9 molecules geometries calculated with 76 different DFT functionals and three different basis sets + resulting in 228 energy values for each molecule along with semi-empirical method GFN2-xTB. Geometries for the + molecules are used directly from Kim et al. which uses G4MP2 method. Usage: ```python - from openqdc.datasets import NablaDFT - dataset = NablaDFT() + from openqdc.datasets import MultixcQM9 + dataset = MultixcQM9() ``` References: - - https://www.nature.com/articles/s41597-023-02690-2 - - https://github.com/chemsurajit/largeDFTdata + https://www.nature.com/articles/s41597-023-02690-2\n + https://github.com/chemsurajit/largeDFTdata\n + https://www.nature.com/articles/s41597-019-0121-7\n """ __name__ = "multixcqm9" diff --git a/openqdc/datasets/potential/nabladft.py b/openqdc/datasets/potential/nabladft.py index 4700ade5..f83f1c00 100644 --- a/openqdc/datasets/potential/nabladft.py +++ b/openqdc/datasets/potential/nabladft.py @@ -52,7 +52,11 @@ class NablaDFT(BaseDataset): """ NablaDFT is a dataset constructed from a subset of the [Molecular Sets (MOSES) dataset](https://github.com/molecularsets/moses) consisting of 1 million molecules - with 5,340,152 unique conformations generated using ωB97X-D/def2-SVP level of theory. + with 5,340,152 unique conformations. Conformations for each molecule are generated in 2 steps. First, a set of + conformations are generated using RDKit. Second, using Butina Clustering Method on conformations, clusters that + cover 95% of the conformations are selected and the centroids of those clusters are selected as the final set. + This results in 1-62 conformations per molecule. For generating quantum properties, Kohn-Sham method at + wB97X-D/def2-XVP levels are used to generate the energy. Usage: ```python @@ -61,8 +65,8 @@ class NablaDFT(BaseDataset): ``` References: - - https://pubs.rsc.org/en/content/articlelanding/2022/CP/D2CP03966D - - https://github.com/AIRI-Institute/nablaDFT + https://pubs.rsc.org/en/content/articlelanding/2022/CP/D2CP03966D\n + https://github.com/AIRI-Institute/nablaDFT """ __name__ = "nabladft" @@ -76,6 +80,15 @@ class NablaDFT(BaseDataset): __forces_unit__ = "hartree/bohr" __links__ = {"nabladft.db": "https://n-usr-31b1j.s3pd12.sbercloud.ru/b-usr-31b1j-qz9/data/moses_db/dataset_full.db"} + @property + def data_types(self): + return { + "atomic_inputs": np.float32, + "position_idx_range": np.int32, + "energies": np.float32, + "forces": np.float32, + } + @requires_package("nablaDFT") def read_raw_entries(self): from nablaDFT.dataset import HamiltonianDatabase diff --git a/openqdc/datasets/potential/orbnet_denali.py b/openqdc/datasets/potential/orbnet_denali.py index 6a7c3f47..1dd70468 100644 --- a/openqdc/datasets/potential/orbnet_denali.py +++ b/openqdc/datasets/potential/orbnet_denali.py @@ -36,10 +36,14 @@ def read_archive(mol_id, conf_dict, base_path, energy_target_names: List[str]) - class OrbnetDenali(BaseDataset): """ - Orbnet Denali is a collection of 2.3 million conformers from 212,905 unique molecules. It performs - DFT (ωB97X-D3/def2-TZVP) calculations on molecules and geometries consisting of organic molecules - and chemistries, with protonation and tautomeric states, non-covalent interactions, common salts, - and counterions, spanning the most common elements in bio and organic chemistry. + Orbnet Denali is a collection of 2.3 million conformers from 212,905 unique molecules. Molecules include a range + of organic molecules with protonation and tautomeric states, non-covalent interactions, common salts, and + counterions, spanning the most common elements in bio and organic chemistry. Geometries are generated in 2 steps. + First, four energy-minimized conformations are generated for each molecule using the ENTOS BREEZE conformer + generator. Second, using the four energy-minimized conformers, non-equilibrium geometries are generated using + normal mode sampling at 300K or ab initio molecular dynamics (AIMD) for 200fs at 500K; using GFN1-xTB level of + theory. Energies are calculated using DFT method wB97X-D3/def2-TZVP and semi-empirical method GFN1-xTB level of + theory. Usage: ```python @@ -48,8 +52,8 @@ class OrbnetDenali(BaseDataset): ``` References: - - https://arxiv.org/pdf/2107.00299.pdf - - https://figshare.com/articles/dataset/OrbNet_Denali_Training_Data/14883867 + https://arxiv.org/abs/2107.00299\n + https://figshare.com/articles/dataset/OrbNet_Denali_Training_Data/14883867 """ __name__ = "orbnet_denali" @@ -74,13 +78,6 @@ def read_raw_entries(self): for mol_id, group in df.groupby("mol_id") } - # print(df.head()) - # tmp = df.to_dict('index') - # for i, k in enumerate(tmp): - # print(k, tmp[k]) - # if i > 10: - # break - # exit() fn = lambda x: read_archive(x[0], x[1], self.root, self.energy_target_names) res = dm.parallelized(fn, list(labels.items()), scheduler="threads", n_jobs=-1, progress=True) samples = sum(res, []) diff --git a/openqdc/datasets/potential/pcqm.py b/openqdc/datasets/potential/pcqm.py index 535b90dc..cd32b838 100644 --- a/openqdc/datasets/potential/pcqm.py +++ b/openqdc/datasets/potential/pcqm.py @@ -66,6 +66,23 @@ def read_preprocessed_archive(path): class PCQM_PM6(BaseDataset): + """ + PubChemQC PM6 (PCQM_PM6) is an exhaustive dataset containing 221 million organic molecules with optimized + molecular geometries and electronic properties. To generate the dataset, only molecules with weights less + than 1000g/mol are considered from the PubChem ftp site. The initial structure is generated using OpenBabel + and then is optimized using geometry optimization with the semi-empirical method PM6. The energies are also + computed using the PM6 method. + + Usage: + ```python + from openqdc.datasets import PCQM_PM6 + dataset = PCQM_PM6() + ``` + + References: + https://pubs.acs.org/doi/abs/10.1021/acs.jcim.0c00740 + """ + __name__ = "pubchemqc_pm6" __energy_methods__ = [PotentialMethod.PM6] @@ -93,6 +110,15 @@ def collate_list(self, list_entries): res = None return res + @property + def data_types(self): + return { + "atomic_inputs": np.float32, + "position_idx_range": np.int32, + "energies": np.float32, + "forces": np.float32, + } + def read_raw_entries(self): arxiv_paths = glob(p_join(self.root, f"{self.__energy_methods__[0]}", "*.pkl")) f = lambda x: self.collate_list(read_preprocessed_archive(x)) @@ -150,6 +176,21 @@ def collate_and_save_list(self, list_entries): class PCQM_B3LYP(PCQM_PM6): + """ + PubChemQC B3LYP/6-31G* (PCQM_B3LYP) comprises of 85 million molecules ranging from essential compounds to + biomolecules. The geometries for the molecule are optimized using PM6. Using the optimized geometry, + the electronic structure and properties are calculated using B3LIP/6-31G* method. + + Usage: + ```python + from openqdc.datasets import PCQM_B3LYP + dataset = PCQM_B3LYP() + ``` + + References: + https://arxiv.org/abs/2305.18454 + """ + __name__ = "pubchemqc_b3lyp" __energy_methods__ = ["b3lyp/6-31g*"] energy_target_names = ["b3lyp"] diff --git a/openqdc/datasets/potential/proteinfragments.py b/openqdc/datasets/potential/proteinfragments.py new file mode 100644 index 00000000..d6289750 --- /dev/null +++ b/openqdc/datasets/potential/proteinfragments.py @@ -0,0 +1,192 @@ +import os +from os.path import join as p_join + +import numpy as np +from tqdm import tqdm + +from openqdc.datasets.base import BaseDataset +from openqdc.methods import PotentialMethod +from openqdc.utils.io import get_local_cache +from openqdc.utils.package_utils import requires_package + + +def convert_entries(r, e, f, z, subset): + coordinates = r + species = z + forces = f + energies = e + n_atoms = coordinates.shape[0] + flattened_coordinates = coordinates[:].reshape((-1, 3)) + xs = np.stack((species[:].flatten(), np.zeros(flattened_coordinates.shape[0])), axis=-1) + res = dict( + name=np.array([subset]), + subset=np.array([subset]), + energies=energies[:].reshape((-1, 1)).astype(np.float64), + atomic_inputs=np.concatenate((xs, flattened_coordinates), axis=-1, dtype=np.float32), + n_atoms=np.array([n_atoms], dtype=np.int32), + forces=forces[:].reshape(-1, 3, 1).astype(np.float32), + ) + return res + + +@requires_package("apsw") +def read_db(path): + database = Database(path) + subset = os.path.basename(path).split(".")[0] + # Read an entry from the database. + # entry = 0 + n = len(database) + entries = [] + for entry in tqdm(range(n)): + q, s, z, r, e, f, d = database[entry] + entries.append(convert_entries(r, e, f, z, subset)) + return entries + + # assert entry < len(database) + # q, s, z, r, e, f, d = database[entry] + # with np.printoptions(threshold=7): + # print(f'entry {entry} of {len(database)}') + # print('total charge\n', q) + # print('number of unpaired electrons\n', s) + # print('atomic numbers\n', z) + # print('positions [Å]\n', r) + # print('energy [eV]\n', e) + # print('forces [eV/Å]\n', f) + # print('dipole [e*Å]\n', d) + + +class Database: + @requires_package("apsw") + def __init__(self, filename): + import apsw + + self.cursor = apsw.Connection(filename, flags=apsw.SQLITE_OPEN_READONLY).cursor() + + def __len__(self): + return self.cursor.execute("""SELECT * FROM metadata WHERE id=1""").fetchone()[-1] + + def __getitem__(self, idx): + data = self.cursor.execute("""SELECT * FROM data WHERE id=""" + str(idx)).fetchone() + return self._unpack_data_tuple(data) + + def _deblob(self, buffer, dtype, shape=None): + array = np.frombuffer(buffer, dtype) + if not np.little_endian: + array = array.byteswap() + array.shape = shape + return np.copy(array) + + def _unpack_data_tuple(self, data): + n = len(data[3]) // 4 # A single int32 is 4 bytes long. + q = np.asarray([0.0 if data[1] is None else data[1]], dtype=np.float32) + s = np.asarray([0.0 if data[2] is None else data[2]], dtype=np.float32) + z = self._deblob(data[3], dtype=np.int32, shape=(n,)) + r = self._deblob(data[4], dtype=np.float32, shape=(n, 3)) + e = np.asarray([0.0 if data[5] is None else data[5]], dtype=np.float32) + f = self._deblob(data[6], dtype=np.float32, shape=(n, 3)) + d = self._deblob(data[7], dtype=np.float32, shape=(1, 3)) + return q, s, z, r, e, f, d + + +class ProteinFragments(BaseDataset): + """ + ProteinFragments is a dataset constructed from a subset of the + the data was generated from a top-down and bottom-up approach: + + Top-down: + Fragments are generated by cutting out a spherical + region around an atom (including solvent molecules) + and saturating all dangling bonds. + Sampling was done with the Molecular Dynamics (MD) method from + conventional FF at room temperature. + + Bottom-up: + Fragments are generated by constructing chemical graphs + of one to eight nonhydrogen atoms. + Sampling of multiple conformers per fragments was done with + MD simulations at high temperatures or normal mode sampling. + + + Usage: + ```python + from openqdc.datasets import ProteinFragments + dataset = ProteinFragments() + ``` + + References: + https://www.science.org/doi/10.1126/sciadv.adn4397 + """ + + __name__ = "proteinfragments" + # PBE0/def2-TZVPP+MBD + __energy_methods__ = [ + PotentialMethod.WB97X_6_31G_D, # "wb97x/6-31g(d)" + ] + + energy_target_names = [ + "ωB97x:6-31G(d) Energy", + ] + # PBE0/def2-TZVPP+MBD + __energy_unit__ = "ev" + __distance_unit__ = "ang" + __forces_unit__ = "ev/ang" + __links__ = { + f"{name}.db": f"https://zenodo.org/records/10720941/files/{name}.db?download=1" + for name in ["general_protein_fragments"] + } + + @property + def root(self): + return p_join(get_local_cache(), "proteinfragments") + + @property + def config(self): + assert len(self.__links__) > 0, "No links provided for fetching" + return dict(dataset_name="proteinfragments", links=self.__links__) + + @property + def preprocess_path(self): + path = p_join(self.root, "preprocessed", self.__name__) + os.makedirs(path, exist_ok=True) + return path + + def read_raw_entries(self): + samples = [] + for name in self.__links__: + raw_path = p_join(self.root, f"{name}") + samples.extend(read_db(raw_path)) + return samples + + +class MDDataset(ProteinFragments): + """ + MDDataset is a subset of the proteinfragments dataset that + generated from the molecular dynamics with their model. + The sampling was done with Molecular Dynamics + at room temperature 300K in various solvent phase: + + Subsets: + Polyalanine: + All the polyalanine are sampled in gas phase. AceAla15Lys is + a polyalanine peptides capped with an N-terminal acetyl group + and a protonated lysine residue at the C-terminus, + Acela15nme is polyalanine peptide capped with an N-terminal acetyl group + and a C-terminal N-methyl amide group\n + Crambin: 46-residue protein crambin in aqueous solution (25,257 atoms) + + Usage: + ```python + from openqdc.datasets import MDDataset + dataset = MDDataset() + ``` + + References: + https://www.science.org/doi/10.1126/sciadv.adn4397 + """ + + __name__ = "mddataset" + + __links__ = { + f"{name}.db": f"https://zenodo.org/records/10720941/files/{name}.db?download=1" + for name in ["acala15nme_folding_clusters", "crambin", "minimahopping_acala15lysh", "minimahopping_acala15nme"] + } diff --git a/openqdc/datasets/potential/qm1b.py b/openqdc/datasets/potential/qm1b.py index 5e10ed23..edccae0d 100644 --- a/openqdc/datasets/potential/qm1b.py +++ b/openqdc/datasets/potential/qm1b.py @@ -78,11 +78,11 @@ def extract_from_row(row, file_idx=None): class QM1B(BaseDataset): """ - QM1B is a low-resolution DFT dataset generated using PySCF IPU. - It is composed of one billion training examples containing 9-11 heavy atoms. - It was created by taking 1.09M SMILES strings from the GDB-11 database and - computing molecular properties (e.g. HOMO-LUMO gap) for a set of up to 1000 - conformers per molecule at the B3LYP/STO-3G level of theory. + QM1B is a dataset containing 1 billion conformations for 1.09M small molecules generated using a custom + PySCF library that incorporates hardware acceleration via IPUs. The molecules contain 9-11 heavy atoms and are + subsampled from the Generated Data Bank (GDB). For each molecule, 1000 geometries are generated using RDKit. + Electronic properties for each conformation are then calculated using the density functional B3LYP + and the basis set STO-3G. Usage: ```python @@ -91,8 +91,8 @@ class QM1B(BaseDataset): ``` References: - - https://arxiv.org/pdf/2311.01135 - - https://github.com/graphcore-research/qm1b-dataset/ + https://arxiv.org/pdf/2311.01135\n + https://github.com/graphcore-research/qm1b-dataset/ """ __name__ = "qm1b" @@ -144,8 +144,7 @@ def extract_parallel(df, i): class QM1B_SMALL(QM1B): """ - QM1B_SMALL is a subset of the QM1B dataset containing a - maximum of 15 random conformers per molecule. + QM1B_SMALL is a subset of the QM1B dataset containing a maximum of 15 random conformers per molecule. Usage: ```python diff --git a/openqdc/datasets/potential/qm7x.py b/openqdc/datasets/potential/qm7x.py index 7bf1323c..351162c0 100644 --- a/openqdc/datasets/potential/qm7x.py +++ b/openqdc/datasets/potential/qm7x.py @@ -35,12 +35,15 @@ def read_mol(mol_h5, mol_name, energy_target_names, force_target_names): class QM7X(BaseDataset): """ - QM7X is a collection of almost 4.2 million conformers from 6,950 unique molecules. It contains DFT - energy and force labels at the PBE0+MBD level of theory. It consists of structures for molecules with - up to seven heavy (C, N, O, S, Cl) atoms from the GDB13 database. For each molecule, (meta-)stable - equilibrium structures including constitutional/structural isomers and stereoisomers are - searched using density-functional tight binding (DFTB). Then, for each (meta-)stable structure, 100 - off-equilibrium structures are obtained and labeled with PBE0+MBD. + QM7X is a collection of almost 4.2 million conformers from 6,950 unique organic molecules. The molecules with + up to seven heavy (C, N, O, S, Cl) atoms are considered from the GDB13 database. For generating conformations, + OpenBabel is utilized to get an initial structure using the MMFF94 force field. Using the initial structure, meta- + stable conformational isomers are generated using the Confab tool along with the MMFF94 force field. The structure + is then re-optimized with density-functional tight binding (DFTB) supplemented with many-body dispersion (MBD) + interactions. The lowest energy structure is then considered as the final equilibrium conformer. Additionally, non + -equilibrium conformations are generated by displacing the equilibrium geometry along a linear combination of + normal mode coordinates computed at the DFTB3-MBD level within the harmonic approximation. The dataset has + energy values for each geometry computed at PBE0-MBD and DFTB3-MBD method. Usage: ```python @@ -49,8 +52,8 @@ class QM7X(BaseDataset): ``` References: - - https://arxiv.org/abs/2006.15139 - - https://zenodo.org/records/4288677 + https://arxiv.org/abs/2006.15139\n + https://zenodo.org/records/4288677 """ __name__ = "qm7x" @@ -59,9 +62,9 @@ class QM7X(BaseDataset): energy_target_names = ["ePBE0+MBD", "eDFTB+MBD"] - __force_mask__ = [True, True] + __force_mask__ = [True, False] - force_target_names = ["pbe0FOR", "vdwFOR"] + force_target_names = ["pbe0FOR"] __energy_unit__ = "ev" __distance_unit__ = "ang" @@ -81,6 +84,16 @@ def read_raw_entries(self): class QM7X_V2(QM7X): + """ + QM7X_V2 is an extension of the QM7X dataset containing PM6 labels for each of the 4.2M geometries. + + Usage: + ```python + from openqdc.datasets import QM7X_V2 + dataset = QM7X_V2() + ``` + """ + __name__ = "qm7x_v2" __energy_methods__ = QM7X.__energy_methods__ + [PotentialMethod.PM6] __force_mask__ = QM7X.__force_mask__ + [False] diff --git a/openqdc/datasets/potential/qmugs.py b/openqdc/datasets/potential/qmugs.py index 6cc38900..b819b214 100644 --- a/openqdc/datasets/potential/qmugs.py +++ b/openqdc/datasets/potential/qmugs.py @@ -38,8 +38,9 @@ def read_mol(mol_dir): class QMugs(BaseDataset): """ The QMugs dataset contains 2 million conformers for 665k biologically and pharmacologically relevant molecules - extracted from the ChEMBL database. The atomic and molecular properties are calculated using both, - semi-empirical methods (GFN2-xTB) and DFT method (ωB97X-D/def2-SVP). + extracted from the ChEMBL database. Three geometries per molecule are generated and optimized using the GFN2-xTB + method. Using the optimized geometry, the atomic and molecular properties are calculated using both, semi-empirical + method (GFN2-xTB) and DFT method (ωB97X-D/def2-SVP). Usage: ```python @@ -48,8 +49,9 @@ class QMugs(BaseDataset): ``` References: - - https://www.nature.com/articles/s41597-022-01390-7#ethics - - https://www.research-collection.ethz.ch/handle/20.500.11850/482129 + https://arxiv.org/abs/2107.00367\n + https://www.nature.com/articles/s41597-022-01390-7#ethics\n + https://www.research-collection.ethz.ch/handle/20.500.11850/482129 """ __name__ = "qmugs" @@ -76,6 +78,16 @@ def read_raw_entries(self): class QMugs_V2(QMugs): + """ + QMugs_V2 is an extension of the QMugs dataset containing PM6 labels for each of the 4.2M geometries. + + Usage: + ```python + from openqdc.datasets import QMugs_V2 + dataset = QMugs_V2() + ``` + """ + __name__ = "qmugs_v2" __energy_methods__ = QMugs.__energy_methods__ + [PotentialMethod.PM6] energy_target_names = QMugs.energy_target_names + ["PM6"] diff --git a/openqdc/datasets/potential/qmx.py b/openqdc/datasets/potential/qmx.py new file mode 100644 index 00000000..2dfb8443 --- /dev/null +++ b/openqdc/datasets/potential/qmx.py @@ -0,0 +1,402 @@ +import os +from abc import ABC +from os.path import join as p_join + +import datamol as dm +import numpy as np +import pandas as pd + +from openqdc.datasets.base import BaseDataset +from openqdc.methods import PotentialMethod +from openqdc.utils import read_qc_archive_h5 +from openqdc.utils.io import get_local_cache +from openqdc.utils.molecule import get_atomic_number_and_charge + + +def extract_ani2_entries(properties): + coordinates = properties["coordinates"] + species = properties["species"] + forces = properties["forces"] + energies = properties["energies"] + n_atoms = coordinates.shape[1] + n_entries = coordinates.shape[0] + flattened_coordinates = coordinates[:].reshape((-1, 3)) + xs = np.stack((species[:].flatten(), np.zeros(flattened_coordinates.shape[0])), axis=-1) + res = dict( + name=np.array(["ANI2"] * n_entries), + subset=np.array([str(n_atoms)] * n_entries), + energies=energies[:].reshape((-1, 1)).astype(np.float64), + atomic_inputs=np.concatenate((xs, flattened_coordinates), axis=-1, dtype=np.float32), + n_atoms=np.array([n_atoms] * n_entries, dtype=np.int32), + forces=forces[:].reshape(-1, 3, 1).astype(np.float32), + ) + return res + + +class QMX(ABC, BaseDataset): + """ + QMX dataset base abstract class + """ + + __name__ = "qm9" + + __energy_methods__ = [ + PotentialMethod.WB97X_6_31G_D, # "wb97x/6-31g(d)" + ] + + energy_target_names = [ + "ωB97x:6-31G(d) Energy", + ] + + __energy_unit__ = "hartree" + __distance_unit__ = "bohr" + __forces_unit__ = "hartree/bohr" + __links__ = {} + + @property + def root(self): + return p_join(get_local_cache(), "qmx") + + @property + def preprocess_path(self): + path = p_join(self.root, "preprocessed", self.__name__) + os.makedirs(path, exist_ok=True) + return path + + @property + def config(self): + assert len(self.__links__) > 0, "No links provided for fetching" + return dict(dataset_name="qmx", links=self.__links__) + + def read_raw_entries(self): + raw_path = p_join(self.root, f"{self.__name__}.h5.gz") + samples = read_qc_archive_h5(raw_path, self.__name__, self.energy_target_names, None) + return samples + + +# ['smiles', 'E1-CC2', 'E2-CC2', 'f1-CC2', 'f2-CC2', 'E1-PBE0', 'E2-PBE0', 'f1-PBE0', 'f2-PBE0', +# 'E1-PBE0.1', 'E2-PBE0.1', 'f1-PBE0.1', 'f2-PBE0.1', 'E1-CAM', 'E2-CAM', 'f1-CAM', 'f2-CAM'] +class QM7(QMX): + """ + QM7 is a dataset constructed from subsets of the GDB-13 database ( + stable and synthetically accessible organic molecules), + containing up to seven “heavy” atoms. + The molecules conformation are optimized using DFT at the + PBE0/def2-TZVP level of theory. + + Chemical species: + [C, N, O, S, H] + + Usage: + ```python + from openqdc.datasets import QM7 + dataset = QM7() + ``` + + References: + https://arxiv.org/pdf/1703.00564 + """ + + __links__ = {"qm7.hdf5.gz": "https://zenodo.org/record/3588337/files/150.hdf5.gz?download=1"} + __name__ = "qm7" + + energy_target_names = [ + "B2PLYP-D3(BJ):aug-cc-pvdz", + "B2PLYP-D3(BJ):aug-cc-pvtz", + "B2PLYP-D3(BJ):def2-svp", + "B2PLYP-D3(BJ):def2-tzvp", + "B2PLYP-D3(BJ):sto-3g", + "B2PLYP-D3:aug-cc-pvdz", + "B2PLYP-D3:aug-cc-pvtz", + "B2PLYP-D3:def2-svp", + "B2PLYP-D3:def2-tzvp", + "B2PLYP-D3:sto-3g", + "B2PLYP-D3M(BJ):aug-cc-pvdz", + "B2PLYP-D3M(BJ):aug-cc-pvtz", + "B2PLYP-D3M(BJ):def2-svp", + "B2PLYP-D3M(BJ):def2-tzvp", + "B2PLYP-D3M(BJ):sto-3g", + "B2PLYP-D3M:aug-cc-pvdz", + "B2PLYP-D3M:aug-cc-pvtz", + "B2PLYP-D3M:def2-svp", + "B2PLYP-D3M:def2-tzvp", + "B2PLYP-D3M:sto-3g", + "B2PLYP:aug-cc-pvdz", + "B2PLYP:aug-cc-pvtz", + "B2PLYP:def2-svp", + "B2PLYP:def2-tzvp", + "B2PLYP:sto-3g", + "B3LYP-D3(BJ):aug-cc-pvdz", + "B3LYP-D3(BJ):aug-cc-pvtz", + "B3LYP-D3(BJ):def2-svp", + "B3LYP-D3(BJ):def2-tzvp", + "B3LYP-D3(BJ):sto-3g", + "B3LYP-D3:aug-cc-pvdz", + "B3LYP-D3:aug-cc-pvtz", + "B3LYP-D3:def2-svp", + "B3LYP-D3:def2-tzvp", + "B3LYP-D3:sto-3g", + "B3LYP-D3M(BJ):aug-cc-pvdz", + "B3LYP-D3M(BJ):aug-cc-pvtz", + "B3LYP-D3M(BJ):def2-svp", + "B3LYP-D3M(BJ):def2-tzvp", + "B3LYP-D3M(BJ):sto-3g", + "B3LYP-D3M:aug-cc-pvdz", + "B3LYP-D3M:aug-cc-pvtz", + "B3LYP-D3M:def2-svp", + "B3LYP-D3M:def2-tzvp", + "B3LYP-D3M:sto-3g", + "B3LYP:aug-cc-pvdz", + "B3LYP:aug-cc-pvtz", + "B3LYP:def2-svp", + "B3LYP:def2-tzvp", + "B3LYP:sto-3g", + "HF:aug-cc-pvdz", + "HF:aug-cc-pvtz", + "HF:def2-svp", + "HF:def2-tzvp", + "HF:sto-3g", + "MP2:aug-cc-pvdz", + "MP2:aug-cc-pvtz", + "MP2:def2-svp", + "MP2:def2-tzvp", + "MP2:sto-3g", + "PBE0:aug-cc-pvdz", + "PBE0:aug-cc-pvtz", + "PBE0:def2-svp", + "PBE0:def2-tzvp", + "PBE0:sto-3g", + "PBE:aug-cc-pvdz", + "PBE:aug-cc-pvtz", + "PBE:def2-svp", + "PBE:def2-tzvp", + "PBE:sto-3g", + "WB97M-V:aug-cc-pvdz", + "WB97M-V:aug-cc-pvtz", + "WB97M-V:def2-svp", + "WB97M-V:def2-tzvp", + "WB97M-V:sto-3g", + "WB97X-D:aug-cc-pvdz", + "WB97X-D:aug-cc-pvtz", + "WB97X-D:def2-svp", + "WB97X-D:def2-tzvp", + "WB97X-D:sto-3g", + ] + + __energy_methods__ = [PotentialMethod.NONE for _ in range(len(energy_target_names))] # "wb97x/6-31g(d)" + + +class QM7b(QMX): + """ + QM7b is a dataset constructed from subsets of the GDB-13 database ( + stable and synthetically accessible organic molecules), + containing up to seven “heavy” atoms. + The molecules conformation are optimized using DFT at the + PBE0/def2-TZVP level of theory. + + Chemical species: + [C, N, O, S, Cl, H] + + Usage: + ```python + from openqdc.datasets import QM7b + dataset = QM7b() + ``` + + References: + https://arxiv.org/pdf/1703.00564 + """ + + __links__ = {"qm7b.hdf5.gz": "https://zenodo.org/record/3588335/files/200.hdf5.gz?download=1"} + __name__ = "qm7b" + energy_target_names = [ + "CCSD(T0):cc-pVDZ", + "HF:cc-pVDZ", + "HF:cc-pVTZ", + "MP2:cc-pVTZ", + "B2PLYP-D3:aug-cc-pvdz", + "B2PLYP-D3:aug-cc-pvtz", + "B2PLYP-D3:def2-svp", + "B2PLYP-D3:def2-tzvp", + "B2PLYP-D3:sto-3g", + "B2PLYP-D3M(BJ):aug-cc-pvdz", + "B2PLYP-D3M(BJ):aug-cc-pvtz", + "B2PLYP-D3M(BJ):def2-svp", + "B2PLYP-D3M(BJ):def2-tzvp", + "B2PLYP-D3M(BJ):sto-3g", + "B2PLYP-D3M:aug-cc-pvdz", + "B2PLYP-D3M:aug-cc-pvtz", + "B2PLYP-D3M:def2-svp", + "B2PLYP-D3M:def2-tzvp", + "B2PLYP-D3M:sto-3g", + "B2PLYP:aug-cc-pvdz", + "B2PLYP:aug-cc-pvtz", + "B2PLYP:def2-svp", + "B2PLYP:def2-tzvp", + "B2PLYP:sto-3g", + "B3LYP-D3(BJ):aug-cc-pvdz", + "B3LYP-D3(BJ):aug-cc-pvtz", + "B3LYP-D3(BJ):def2-svp", + "B3LYP-D3(BJ):def2-tzvp", + "B3LYP-D3(BJ):sto-3g", + "B3LYP-D3:aug-cc-pvdz", + "B3LYP-D3:aug-cc-pvtz", + "B3LYP-D3:def2-svp", + "B3LYP-D3:def2-tzvp", + "B3LYP-D3:sto-3g", + "B3LYP-D3M(BJ):aug-cc-pvdz", + "B3LYP-D3M(BJ):aug-cc-pvtz", + "B3LYP-D3M(BJ):def2-svp", + "B3LYP-D3M(BJ):def2-tzvp", + "B3LYP-D3M(BJ):sto-3g", + "B3LYP-D3M:aug-cc-pvdz", + "B3LYP-D3M:aug-cc-pvtz", + "B3LYP-D3M:def2-svp", + "B3LYP-D3M:def2-tzvp", + "B3LYP-D3M:sto-3g", + "B3LYP:aug-cc-pvdz", + "B3LYP:aug-cc-pvtz", + "B3LYP:def2-svp", + "B3LYP:def2-tzvp", + "B3LYP:sto-3g", + "HF:aug-cc-pvdz", + "HF:aug-cc-pvtz", + "HF:cc-pvtz", + "HF:def2-svp", + "HF:def2-tzvp", + "HF:sto-3g", + "PBE0:aug-cc-pvdz", + "PBE0:aug-cc-pvtz", + "PBE0:def2-svp", + "PBE0:def2-tzvp", + "PBE0:sto-3g", + "PBE:aug-cc-pvdz", + "PBE:aug-cc-pvtz", + "PBE:def2-svp", + "PBE:def2-tzvp", + "PBE:sto-3g", + "SVWN:sto-3g", + "WB97M-V:aug-cc-pvdz", + "WB97M-V:aug-cc-pvtz", + "WB97M-V:def2-svp", + "WB97M-V:def2-tzvp", + "WB97M-V:sto-3g", + "WB97X-D:aug-cc-pvdz", + "WB97X-D:aug-cc-pvtz", + "WB97X-D:def2-svp", + "WB97X-D:def2-tzvp", + "WB97X-D:sto-3g", + ] + __energy_methods__ = [PotentialMethod.NONE for _ in range(len(energy_target_names))] # "wb97x/6-31g(d)"] + + +class QM8(QMX): + """QM8 is the subset of QM9 used in a study on modeling quantum + mechanical calculations of electronic spectra and excited + state energy (a increase of energy from the ground states) of small molecules + up to eight heavy atoms. + Multiple methods were used, including + time-dependent density functional theories (TDDFT) and + second-order approximate coupled-cluster (CC2). + The molecules conformations are relaxed geometries computed using + the DFT B3LYP with basis set 6-31G(2df,p). + For more information about the sampling, check QM9 dataset. + + Usage: + ```python + from openqdc.datasets import QM8 + dataset = QM8() + ``` + + References: + https://arxiv.org/pdf/1504.01966 + """ + + __name__ = "qm8" + + __energy_methods__ = [ + PotentialMethod.NONE, # "wb97x/6-31g(d)" + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + ] + + __links__ = { + "qm8.csv": "https://deepchemdata.s3-us-west-1.amazonaws.com/datasets/qm8.csv", + "qm8.tar.gz": "https://deepchemdata.s3-us-west-1.amazonaws.com/datasets/gdb8.tar.gz", + } + + def read_raw_entries(self): + df = pd.read_csv(p_join(self.root, "qm8.csv")) + mols = dm.read_sdf(p_join(self.root, "qm8.sdf"), sanitize=False, remove_hs=False) + samples = [] + for idx_row, mol in zip(df.iterrows(), mols): + _, row = idx_row + positions = mol.GetConformer().GetPositions() + x = get_atomic_number_and_charge(mol) + n_atoms = positions.shape[0] + samples.append( + dict( + atomic_inputs=np.concatenate((x, positions), axis=-1, dtype=np.float32).reshape(-1, 5), + name=np.array([row["smiles"]]), + energies=np.array( + [ + row[ + ["E1-CC2", "E2-CC2", "E1-PBE0", "E2-PBE0", "E1-PBE0.1", "E2-PBE0.1", "E1-CAM", "E2-CAM"] + ].tolist() + ], + dtype=np.float64, + ).reshape(1, -1), + n_atoms=np.array([n_atoms], dtype=np.int32), + subset=np.array([f"{self.__name__}"]), + ) + ) + return samples + + +class QM9(QMX): + """ + QM7b is a dataset constructed containing 134k molecules from subsets of the GDB-17 database, + containing up to 9 “heavy” atoms. All molecular properties are calculated at B3LUP/6-31G(2df,p) + level of quantum chemistry. For each of the 134k molecules, equilibrium geometries are computed + by relaxing geometries with quantum mechanical method B3LYP. + + Usage: + ```python + from openqdc.datasets import QM9 + dataset = QM9() + ``` + + Reference: + https://www.nature.com/articles/sdata201422 + """ + + __links__ = {"qm9.hdf5.gz": "https://zenodo.org/record/3588339/files/155.hdf5.gz?download=1"} + __name__ = "qm9" + energy_target_names = [ + "Internal energy at 0 K", + "B3LYP:def2-svp", + "HF:cc-pvtz", + "HF:sto-3g", + "PBE:sto-3g", + "SVWN:sto-3g", + "WB97X-D:aug-cc-pvtz", + "WB97X-D:def2-svp", + "WB97X-D:def2-tzvp", + ] + + __energy_methods__ = [ + PotentialMethod.NONE, # "wb97x/6-31g(d)" + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + PotentialMethod.NONE, + ] diff --git a/openqdc/datasets/potential/revmd17.py b/openqdc/datasets/potential/revmd17.py index 613ce91f..425f9784 100644 --- a/openqdc/datasets/potential/revmd17.py +++ b/openqdc/datasets/potential/revmd17.py @@ -54,23 +54,27 @@ def create_path(filename, root): class RevMD17(BaseDataset): """ - - Benzene: 627000 samples - - Uracil: 133000 samples - - Naptalene: 326000 samples - - Aspirin: 211000 samples - - Salicylic Acid: 320000 samples - - Malonaldehyde: 993000 samples - - Ethanol: 555000 samples - - Toluene: 100000 samples - - Usage + Revised MD (RevMD17) improves upon the MD17 dataset by removing all the numerical noise present in the original + dataset. The data is generated from an ab-initio molecular dynamics (AIMD) simulation where forces and energies + are computed at the PBE/def2-SVP level of theory using very tigh SCF convergence and very dense DFT integration + grid. The dataset contains the following molecules: + Benzene: 627000 samples\n + Uracil: 133000 samples\n + Naptalene: 326000 samples\n + Aspirin: 211000 samples\n + Salicylic Acid: 320000 samples\n + Malonaldehyde: 993000 samples\n + Ethanol: 555000 samples\n + Toluene: 100000 samples\n + + Usage: ```python from openqdc.datasets import RevMD17 dataset = RevMD17() ``` References: - - https://arxiv.org/abs/2007.09593 + https://arxiv.org/abs/2007.09593 """ __name__ = "revmd17" diff --git a/openqdc/datasets/potential/sn2_rxn.py b/openqdc/datasets/potential/sn2_rxn.py index 29337573..2194775b 100644 --- a/openqdc/datasets/potential/sn2_rxn.py +++ b/openqdc/datasets/potential/sn2_rxn.py @@ -39,10 +39,12 @@ def extract_npz_entry(data): class SN2RXN(BaseDataset): """ - This dataset probes chemical reactions of methyl halides with halide anions, i.e. - X- + CH3Y -> CH3X + Y-, and contains structures for all possible combinations of - X,Y = F, Cl, Br, I. It contains energy and forces for 452709 conformations calculated - at the DSD-BLYP-D3(BJ)/def2-TZVP level of theory. + This dataset probes chemical reactions of methyl halides with halide anions, i.e. X- + CH3Y -> CH3X + Y-, and + contains structures for all possible combinations of X,Y = F, Cl, Br, I. The conformations are generated by + running MD simulations at a temperature of 5000K with a time step of 0.1 fs using Atomic Simulation Environment + (ASE). The forces are derived using semi-empirical method PM7 and the structures are saved every 10 steps, and + for each of them, energy and forces are calculated at the DSD-BLYP-D3(BJ)/def2-TZVP level of theory. The dataset + contains 452,709 structures along with the energy, force and dipole moments. Usage: ```python @@ -51,8 +53,8 @@ class SN2RXN(BaseDataset): ``` References: - - https://doi.org/10.1021/acs.jctc.9b00181 - - https://zenodo.org/records/2605341 + https://doi.org/10.1021/acs.jctc.9b00181\n + https://zenodo.org/records/2605341 """ __name__ = "sn2_rxn" diff --git a/openqdc/datasets/potential/solvated_peptides.py b/openqdc/datasets/potential/solvated_peptides.py index 4fead36f..f00e1a05 100644 --- a/openqdc/datasets/potential/solvated_peptides.py +++ b/openqdc/datasets/potential/solvated_peptides.py @@ -7,10 +7,10 @@ class SolvatedPeptides(BaseDataset): """ - The solvated protein fragments dataset probes many-body intermolecular - interactions between "protein fragments" and water molecules. - It contains energy and forces for 2731180 structures calculated - at the revPBE-D3(BJ)/def2-TZVP level of theory. + The solvated protein fragments dataset probes many-body intermolecular interactions between "protein fragments" + and water molecules. Geometries are first optimized with the semi-empirical method PM7 and then MD simulations are + run at 1000K with a time-step of 0.1fs using Atomic Simulations Environment (ASE). Structures are saved every 10 + steps, where energies, forces and dipole moments are calculated at revPBE-D3(BJ)/def2-TZVP level of theory. Usage: ```python @@ -19,8 +19,8 @@ class SolvatedPeptides(BaseDataset): ``` References: - - https://doi.org/10.1021/acs.jctc.9b00181 - - https://zenodo.org/records/2605372 + https://doi.org/10.1021/acs.jctc.9b00181\n + https://zenodo.org/records/2605372 """ __name__ = "solvated_peptides" diff --git a/openqdc/datasets/potential/spice.py b/openqdc/datasets/potential/spice.py index 27525bb4..2f8cc36f 100644 --- a/openqdc/datasets/potential/spice.py +++ b/openqdc/datasets/potential/spice.py @@ -40,9 +40,12 @@ def read_record(r, obj): class Spice(BaseDataset): """ - The Spice dataset consists of 1.1 million conformations for a diverse set of 19k unique molecules consisting of - small molecules, dimers, dipeptides, and solvated amino acids. It consists of both forces and energies calculated - at the {\omega}B97M-D3(BJ)/def2-TZVPPD level of theory. + Spice dataset consists of 1.1 million conformations for a diverse set of 19k unique molecules consisting of + small molecules, dimers, dipeptides, and solvated amino acids. Conformations are first generated with RDKit, + and then molecular dynamics simulations at 100ps and 500K using OpenMM and Amber force field are used to generate + 100 high energy conformations. Low-energy conformations are then generated by L-BFGS energy minimization and + molecular dynamics at 1ps and 100K. Forces and energies for conformations are calculated at the + wB97M-D3(BJ)/def2-TZVPPD level of theory. Usage: ```python @@ -51,8 +54,8 @@ class Spice(BaseDataset): ``` References: - - https://arxiv.org/abs/2209.10702 - - https://github.com/openmm/spice-dataset + https://arxiv.org/abs/2209.10702\n + https://github.com/openmm/spice-dataset """ __name__ = "spice" @@ -96,10 +99,11 @@ def read_raw_entries(self): class SpiceV2(Spice): """ - SpiceV2 dataset augmented with amino acids complexes, water boxes, - pubchem solvated molecules. - It consists of both forces and energies calculated - at the {\omega}B97M-D3(BJ)/def2-TZVPPD level of theory. + SpiceV2 dataset augments the Spice data with amino acids complexes, water boxes, pubchem solvated molecules. + The main changes include, (1) over 13,000 new PubChem molecules, out of which 1500 contain boron and 1900 contain + silicon, (2) 194,000 conformations of dimers containing amino acid and ligands, (3) 1000 water clusters to improve + sampling interactions in bulk water, (4) 1397 PubChem molecules solvated with a shell of water molecules, and + (5) Fixing bad calculations from the Spice dataset. The data generation process is the same as the Spice dataset. Usage: ```python @@ -108,8 +112,8 @@ class SpiceV2(Spice): ``` References: - - https://github.com/openmm/spice-dataset/releases/tag/2.0.0 - - https://github.com/openmm/spice-dataset + https://github.com/openmm/spice-dataset/releases/tag/2.0.0\n + https://github.com/openmm/spice-dataset """ __name__ = "spicev2" @@ -150,6 +154,20 @@ def read_raw_entries(self): class SpiceVL2(SpiceV2): + """ + SpiceVL2 is an extension of the SpiceV2 dataset with additional semi-empirical GFN2-xTB and PM6 energy methods. + + Usage: + ```python + from openqdc.datasets import SpiceVL2 + dataset = SpiceVL2() + ``` + + References: + https://github.com/openmm/spice-dataset/releases/tag/2.0.0\n + https://github.com/openmm/spice-dataset + """ + __name__ = "spice_vl2" __energy_methods__ = SpiceV2.__energy_methods__ + [PotentialMethod.GFN2_XTB, PotentialMethod.PM6] diff --git a/openqdc/datasets/potential/tmqm.py b/openqdc/datasets/potential/tmqm.py index 1da6901a..987fa10f 100644 --- a/openqdc/datasets/potential/tmqm.py +++ b/openqdc/datasets/potential/tmqm.py @@ -47,10 +47,10 @@ def read_xyz(fname, e_map): class TMQM(BaseDataset): """ - The tmQM dataset contains the geometries of a large transition metal-organic - compound space with a large variety of organic ligands and 30 transition metals. - It contains energy labels for 86,665 mononuclear complexe calculated - at the TPSSh-D3BJ/def2-SV DFT level of theory. + tmQM dataset contains the geometries of a large transition metal-organic compound space with a large variety of + organic ligands and 30 transition metals. It contains energy labels for 86,665 mononuclear complexes calculated + at the TPSSh-D3BJ/def2-SV DFT level of theory. Structures are first extracted from Cambridge Structure Database + and then optimized in gas phase with the extended tight-binding GFN2-xTB method. Usage: ```python @@ -59,8 +59,8 @@ class TMQM(BaseDataset): ``` References: - - https://pubs.acs.org/doi/10.1021/acs.jcim.0c01041 - - https://github.com/bbskjelstad/tmqm + https://pubs.acs.org/doi/10.1021/acs.jcim.0c01041\n + https://github.com/bbskjelstad/tmqm """ __name__ = "tmqm" diff --git a/openqdc/datasets/potential/transition1x.py b/openqdc/datasets/potential/transition1x.py index 8b5b4bc1..d15d71c1 100644 --- a/openqdc/datasets/potential/transition1x.py +++ b/openqdc/datasets/potential/transition1x.py @@ -39,9 +39,9 @@ def read_record(r, group): class Transition1X(BaseDataset): """ - The Transition1x dataset contains structures from 10k organic reaction pathways of various types. - It contains DFT energy and force labels for 9.6 mio. conformers calculated at the - wB97x/6-31-G(d) level of theory. + Transition1x dataset contains structures from 10k organic reaction pathways of various types. It contains energy + and force labels for 9.6 mio. conformers calculated at the wB97x/6-31-G(d) level of theory. The geometries and + the transition states are generated by running Nudged Elastic Band (NEB) with DFT. Usage: ```python @@ -50,8 +50,8 @@ class Transition1X(BaseDataset): ``` References: - - https://www.nature.com/articles/s41597-022-01870-w - - https://gitlab.com/matschreiner/Transition1x + - https://www.nature.com/articles/s41597-022-01870-w\n + - https://gitlab.com/matschreiner/Transition1x\n """ __name__ = "transition1x" diff --git a/openqdc/datasets/potential/vqm24.py b/openqdc/datasets/potential/vqm24.py new file mode 100644 index 00000000..1710e1dd --- /dev/null +++ b/openqdc/datasets/potential/vqm24.py @@ -0,0 +1,82 @@ +import os +from os.path import join as p_join + +import numpy as np + +from openqdc.datasets.base import BaseDataset +from openqdc.methods import PotentialMethod + + +def shape_atom_inputs(coords, atom_species): + xs = np.stack((atom_species, np.zeros_like(atom_species)), axis=-1) + return np.concatenate((xs, coords), axis=-1, dtype=np.float32) + + +def read_npz_entry(raw_path): + samples = np.load(raw_path, allow_pickle=True) + # get name of file without extension + subset = os.path.basename(raw_path).split(".")[0] + + # atoms + # coordinates + coordinates = np.concatenate(samples["coordinates"]) + atom_species = np.concatenate(samples["atoms"]).ravel() + names = list(map(lambda x: x.split("_")[0], samples["compounds"])) + n_comps = len(names) + + # graphs + # inchi + # Etot + # Eatomization + res = dict( + name=np.array(list(map(lambda x: x.split("_")[0], samples["compounds"]))), + subset=np.array([subset] * n_comps), + energies=samples["Etot"][:, None].astype(np.float64), + atomic_inputs=shape_atom_inputs(coordinates, atom_species), + n_atoms=np.array(list(map(lambda x: len(x), samples["coordinates"])), dtype=np.int32), + ) + return res + + +# graphs is smiles +class VQM24(BaseDataset): + """ + Vector-QM24 (VQM24) dataset consists of small organic and inorganic molecules with quantum mechanical + properties calculated at wB97x-D3//cc-pVDZ level of theory. This leads to 258,242 unique constitutional + isomers and 577,705 conformers of varying stoichiometries. Geometries are generated using GFN2-xTB, and + relaxed with DFT method wB97x-D3/cc-pVDZ. The energy values are calculated with DFT method wB97x-D3/cc-pVDZ. + + Usage: + ```python + from openqdc.datasets import VQM24 + dataset = VQM24() + ``` + + Reference: + https://arxiv.org/abs/2405.05961 + """ + + __name__ = "vqm24" + + __energy_methods__ = [ + PotentialMethod.WB97X_6_31G_D, # "wb97x/6-31g(d)" + ] + + energy_target_names = [ + "ωB97x:6-31G(d) Energy", + ] + # ωB97X-D3/cc-pVDZ + __energy_unit__ = "hartree" + __distance_unit__ = "ang" + __forces_unit__ = "hartree/ang" + __links__ = { + f"{name}.npz": f"https://zenodo.org/records/11164951/files/{name}.npz?download=1" + for name in ["DFT_all", "DFT_saddles", "DFT_uniques", "DMC"] + } + + def read_raw_entries(self): + samples = [] + for name in self.__links__: + raw_path = p_join(self.root, f"{name}") + samples.append(read_npz_entry(raw_path)) + return samples diff --git a/openqdc/datasets/potential/waterclusters.py b/openqdc/datasets/potential/waterclusters.py new file mode 100644 index 00000000..8c791474 --- /dev/null +++ b/openqdc/datasets/potential/waterclusters.py @@ -0,0 +1,175 @@ +from collections import defaultdict +from os.path import join as p_join + +import numpy as np + +from openqdc.datasets.base import BaseDataset +from openqdc.methods import PotentialMethod +from openqdc.utils.package_utils import requires_package + +_default_basis_sets = { + "BEGDB_H2O": "aug-cc-pVQZ", + "WATER27": "aug-cc-pVQZ", + "H2O_alkali_clusters": "def2-QZVPPD", + "H2O_halide_clusters": "def2-QZVPPD", +} + + +@requires_package("monty") +@requires_package("pymatgen") +def read_geometries(fname, dataset): + from monty.serialization import loadfn + + geometries = {k: v.to_ase_atoms() for k, v in loadfn(fname)[dataset].items()} + return geometries + + +@requires_package("monty") +def read_energies(fname, dataset): + from monty.serialization import loadfn + + # fname + _energies = loadfn(fname)[dataset] + metadata_restrictions = {"basis_set": _default_basis_sets.get(dataset)} + + functionals_to_return = [] + for dfa, at_dfa_d in _energies.items(): + functionals_to_return += [f"{dfa}" if dfa == at_dfa else f"{dfa}@{at_dfa}" for at_dfa in at_dfa_d] + + energies = defaultdict(dict) + for f in functionals_to_return: + if "-FLOSIC" in f and "@" not in f: + func = f.split("-FLOSIC")[0] + at_f = "-FLOSIC" + else: + func = f.split("@")[0] + at_f = f.split("@")[-1] + + if func not in _energies: + print(f"No functional {func} included in dataset" f"- available options:\n{', '.join(_energies.keys())}") + elif at_f not in _energies[func]: + print( + f"No @functional {at_f} included in {func} dataset" + f"- available options:\n{', '.join(_energies[func].keys())}" + ) + else: + if isinstance(_energies[func][at_f], list): + for entry in _energies[func][at_f]: + if all(entry["metadata"].get(k) == v for k, v in metadata_restrictions.items()): + energies[f] = entry + break + else: + energies[f] = _energies[func][at_f] + return dict(energies) + + +def extract_desc(atom): + # atom_dict=atom.__dict__ + # arrays -> numbers, positions + # charge, spin_multiplicity + pos = atom.get_positions() + z = atom.get_atomic_numbers() + charges = atom.get_initial_charges() + formula = atom.get_chemical_formula() + return pos, z, charges, formula + + +def format_geometry_and_entries(geometries, energies, subset): + entries_list = [] + for entry, atoms in geometries.items(): + pos, z, charges, formula = extract_desc(atoms) + energies_list = [] + for level_of_theory, entry_en_dict in energies.items(): + en = entry_en_dict.get(entry, np.nan) + energies_list.append(en) + energy_array = np.array(energies_list) + if subset in ["WATER27", "H2O_alkali_clusters", "H2O_halide_clusters"]: + # only the first 9 energies are available + energy_array.resize(19) + energy_array[energy_array == 0] = np.nan + res = dict( + atomic_inputs=np.concatenate( + (np.hstack((z[:, None], charges[:, None])), pos), axis=-1, dtype=np.float32 + ).reshape(-1, 5), + name=np.array([formula]), + energies=np.array(energy_array, dtype=np.float64).reshape(1, -1), + n_atoms=np.array([pos.shape[0]], dtype=np.int32), + subset=np.array([subset]), + ) + entries_list.append(res) + return entries_list + + +class SCANWaterClusters(BaseDataset): + """ + The SCAN Water Clusters dataset contains conformations of + neutral water clusters containing up to 20 monomers, charged water clusters, + and alkali- and halide-water clusters. This dataset consists of our data sets of water clusters: + the benchmark energy and geometry database (BEGDB) neutral water cluster subset; the WATER2723 set of 14 + neutral, 5 protonated, 7 deprotonated, and one auto-ionized water cluster; and two sets of + ion-water clusters M...(H2O)n, where M = Li+, Na+, K+, F−, Cl−, or Br−. + Water clusters were obtained from 10 nanosecond gas-phase molecular dynamics + simulations using AMBER 9 and optimized to obtain + lowest energy isomers were determined using MP2/aug-cc-pVDZ//MP2/6-31G* Gibbs free energies. + + + Chemical Species: + [H, O, Li, Na, K, F, Cl, Br] + + Usage: + ```python + from openqdc.datasets import SCANWaterClusters + dataset = SCANWaterClusters() + ``` + + References: + https://chemrxiv.org/engage/chemrxiv/article-details/662aaff021291e5d1db7d8ec\n + https://github.com/esoteric-ephemera/water_cluster_density_errors + """ + + __name__ = "scanwaterclusters" + + __energy_unit__ = "hartree" + __distance_unit__ = "ang" + __forces_unit__ = "hartree/ang" + energy_target_names = [ + "HF", + "HF-r2SCAN-DC4", + "SCAN", + "SCAN@HF", + "SCAN@r2SCAN50", + "r2SCAN", + "r2SCAN@HF", + "r2SCAN@r2SCAN50", + "r2SCAN50", + "r2SCAN100", + "r2SCAN10", + "r2SCAN20", + "r2SCAN25", + "r2SCAN30", + "r2SCAN40", + "r2SCAN60", + "r2SCAN70", + "r2SCAN80", + "r2SCAN90", + ] + __energy_methods__ = [PotentialMethod.NONE for _ in range(len(energy_target_names))] + force_target_names = [] + # 27 # 9 level + subsets = ["BEGDB_H2O", "WATER27", "H2O_alkali_clusters", "H2O_halide_clusters"] + __links__ = { + "geometries.json.gz": "https://github.com/esoteric-ephemera/water_cluster_density_errors/blob/main/data_files/geometries.json.gz?raw=True", # noqa + "total_energies.json.gz": "https://github.com/esoteric-ephemera/water_cluster_density_errors/blob/main/data_files/total_energies.json.gz?raw=True", # noqa + } + + def read_raw_entries(self): + entries = [] # noqa + for i, subset in enumerate(self.subsets): + geometries = read_geometries(p_join(self.root, "geometries.json.gz"), subset) + energies = read_energies(p_join(self.root, "total_energies.json.gz"), subset) + datum = {} + for k in energies: + _ = energies[k].pop("metadata") + datum[k] = energies[k]["total_energies"] + entries.extend(format_geometry_and_entries(geometries, datum, subset)) + return entries diff --git a/openqdc/datasets/potential/waterclusters3_30.py b/openqdc/datasets/potential/waterclusters3_30.py index f4c7d88e..a52b9e17 100644 --- a/openqdc/datasets/potential/waterclusters3_30.py +++ b/openqdc/datasets/potential/waterclusters3_30.py @@ -53,6 +53,10 @@ class WaterClusters(BaseDataset): clusters of sizes n = 3 - 30. The cluster structures are derived and labeled with the TTM2.1-F ab-initio based interaction potential for water. It contains approximately 4.5 mil. structures. + Sampling was done with the Monte Carlo Temperature Basin Paving (MCTBP) method. + + Chemical Species: + ["H", "O"] Usage: ```python @@ -61,8 +65,8 @@ class WaterClusters(BaseDataset): ``` References: - - https://doi.org/10.1063/1.5128378 - - https://sites.uw.edu/wdbase/database-of-water-clusters/ + https://doi.org/10.1063/1.5128378\n + https://sites.uw.edu/wdbase/database-of-water-clusters/\n """ __name__ = "waterclusters3_30" diff --git a/openqdc/datasets/statistics.py b/openqdc/datasets/statistics.py index d471387b..6b1adeb5 100644 --- a/openqdc/datasets/statistics.py +++ b/openqdc/datasets/statistics.py @@ -2,7 +2,7 @@ from copy import deepcopy from dataclasses import asdict, dataclass from os.path import join as p_join -from typing import Optional +from typing import Callable, Dict, Optional import numpy as np from loguru import logger @@ -17,9 +17,15 @@ class StatisticsResults: """ def to_dict(self): + """ + Convert the class to a dictionary + """ return asdict(self) - def transform(self, func): + def transform(self, func: Callable): + """ + Apply a function to all the attributes of the class + """ for k, v in self.to_dict().items(): if v is not None: setattr(self, k, func(v)) @@ -55,6 +61,14 @@ class StatisticManager: """ def __init__(self, dataset, recompute: bool = False, *statistic_calculators: "AbstractStatsCalculator"): + """ + dataset : openqdc.datasets.base.BaseDataset + The dataset object to compute the statistics + recompute : bool, default = False + Flag to recompute the statistics + *statistic_calculators : AbstractStatsCalculator + statistic calculators to run + """ self._state = {} self._results = {} self._statistic_calculators = [ @@ -63,7 +77,7 @@ def __init__(self, dataset, recompute: bool = False, *statistic_calculators: "Ab ] @property - def state(self) -> dict: + def state(self) -> Dict: """ Return the dictionary state of the manager """ @@ -120,7 +134,7 @@ class AbstractStatsCalculator(ABC): """ Abstract class that defines the interface for all the calculators object and the methods to - compute the statistics + compute the statistics. """ # State Dependencies of the calculator to skip part of the calculation @@ -140,6 +154,28 @@ def __init__( atom_charges: Optional[np.ndarray] = None, forces: Optional[np.ndarray] = None, ): + """ + name : str + Name of the dataset for saving and loading. + energy_type : str, default = None + Type of the energy for the computation of the statistics. Used for loading and saving. + force_recompute : bool, default = False + Flag to force the recomputation of the statistics + energies : np.ndarray, default = None + Energies of the dataset + n_atoms : np.ndarray, default = None + Number of atoms in the dataset + atom_species : np.ndarray, default = None + Atomic species of the dataset + position_idx_range : np.ndarray, default = None + Position index range of the dataset + e0_matrix : np.ndarray, default = None + Isolated atom energies matrix of the dataset + atom_charges : np.ndarray, default = None + Atomic charges of the dataset + forces : np.ndarray, default = None + Forces of the dataset + """ self.name = name self.energy_type = energy_type self.force_recompute = force_recompute @@ -149,6 +185,7 @@ def __init__( self.e0_matrix = e0_matrix self.n_atoms = n_atoms self.atom_species_charges_tuple = (atom_species, atom_charges) + self._root = p_join(get_local_cache(), self.name) if atom_species is not None and atom_charges is not None: # by value not reference self.atom_species_charges_tuple = np.concatenate((atom_species[:, None], atom_charges[:, None]), axis=-1) @@ -159,7 +196,7 @@ def has_forces(self) -> bool: @property def preprocess_path(self): - path = p_join(self.root, "preprocessed", str(self) + ".pkl") + path = p_join(self.root, "statistics", self.name + f"_{str(self)}" + ".pkl") return path @property @@ -167,14 +204,14 @@ def root(self): """ Path to the dataset folder """ - return p_join(get_local_cache(), self.name) + return self._root @classmethod def from_openqdc_dataset(cls, dataset, recompute: bool = False): """ - Create a calculator object from a dataset object + Create a calculator object from a dataset object. """ - return cls( + obj = cls( name=dataset.__name__, force_recompute=recompute, energy_type=dataset.energy_type, @@ -186,6 +223,8 @@ def from_openqdc_dataset(cls, dataset, recompute: bool = False): atom_charges=dataset.data["atomic_inputs"][:, 1].ravel(), e0_matrix=dataset.__isolated_atom_energies__, ) + obj._root = dataset.root # set to the dataset root in case of multiple datasets + return obj @abstractmethod def compute(self) -> StatisticsResults: @@ -214,7 +253,7 @@ def attempt_load(self) -> bool: logger.warning(f"Statistics for {str(self)} not found. Computing...") return False - def _setup_deps(self, state: dict) -> None: + def _setup_deps(self, state: Dict) -> None: """ Check if the dependencies of calculators are satisfied from the state object and set the attributes of the calculator @@ -226,7 +265,7 @@ def _setup_deps(self, state: dict) -> None: for dep in self.state_dependency: setattr(self, dep, state[dep]) - def write_state(self, update: dict) -> None: + def write_state(self, update: Dict) -> None: """ Write/update the state dictionary with the update dictionary @@ -235,7 +274,7 @@ def write_state(self, update: dict) -> None: """ self.state.update(update) - def run(self, state: dict) -> None: + def run(self, state: Dict) -> None: """ Main method to run the calculator. Setup the dependencies from the state dictionary diff --git a/openqdc/datasets/structure.py b/openqdc/datasets/structure.py new file mode 100644 index 00000000..f6dc077e --- /dev/null +++ b/openqdc/datasets/structure.py @@ -0,0 +1,276 @@ +import pickle as pkl +from abc import ABC, abstractmethod +from os import PathLike +from os.path import join as p_join +from typing import Callable, Dict, List, Optional, Tuple, Union + +import numpy as np +import zarr + +from openqdc.utils.io import pull_locally + + +class GeneralStructure(ABC): + """ + Abstract Factory class for datasets type in the openQDC package. + """ + + _ext: Optional[str] = None + _extra_files: Optional[List[str]] = None + + @property + def ext(self): + return self._ext + + @property + @abstractmethod + def load_fn(self) -> Callable: + """ + Function to use for loading the data. + Must be implemented by the child class. + + Returns: + the function to use for loading the data + """ + raise NotImplementedError + + def add_extension(self, filename: str) -> str: + """ + Add the correct extension to a filename + + Parameters: + filename: the filename to add the extension to + + Returns: + the filename with the extension + """ + return filename + self.ext + + @abstractmethod + def save_preprocess( + self, + preprocess_path: Union[str, PathLike], + data_keys: List[str], + data_dict: Dict[str, np.ndarray], + extra_data_keys: List[str], + extra_data_types: Dict[str, type], + ) -> List[str]: + """ + Save the preprocessed data to the cache directory and optionally upload it to the remote storage. + Must be implemented by the child class. + + Parameters: + preprocess_path: path to the preprocessed data file + data_keys: list of keys to load from the data file + data_dict: dictionary of data to save + extra_data_keys: list of keys to load from the extra data file + extra_data_types: dictionary of data types for each key + """ + raise NotImplementedError + + @abstractmethod + def load_extra_files( + self, + data: Dict[str, np.ndarray], + preprocess_path: Union[str, PathLike], + data_keys: List[str], + pkl_data_keys: List[str], + overwrite: bool, + ): + """ + Load extra files required to define other types of data. + Must be implemented by the child class. + + Parameters: + data: dictionary of data to load + preprocess_path: path to the preprocessed data file + data_keys: list of keys to load from the data file + pkl_data_keys: list of keys to load from the extra files + overwrite: whether to overwrite the local cache + """ + raise NotImplementedError + + def join_and_ext(self, path: Union[str, PathLike], filename: str) -> Union[str, PathLike]: + """ + Join a path and a filename and add the correct extension. + + Parameters: + path: the path to join + filename: the filename to join + + Returns: + the joined path with the correct extension + """ + return p_join(path, self.add_extension(filename)) + + def load_data( + self, + preprocess_path: Union[str, PathLike], + data_keys: List[str], + data_types: Dict[str, np.dtype], + data_shapes: Dict[str, Tuple[int, int]], + extra_data_keys: List[str], + overwrite: bool, + ): + """ + Main method to load the data from a filetype structure like memmap or zarr. + + Parameters: + preprocess_path: path to the preprocessed data file + data_keys: list of keys to load from the data file + data_types: dictionary of data types for each key + data_shapes: dictionary of shapes for each key + extra_data_keys: list of keys to load from the extra data file + overwrite: whether to overwrite the local cache + """ + data = {} + for key in data_keys: + filename = self.join_and_ext(preprocess_path, key) + pull_locally(filename, overwrite=overwrite) + data[key] = self.load_fn(filename, mode="r", dtype=data_types[key]) + data[key] = self.unpack(data[key]) + data[key] = data[key].reshape(*data_shapes[key]) + + data = self.load_extra_files(data, preprocess_path, data_keys, extra_data_keys, overwrite) + return data + + def unpack(self, data: any) -> any: + """ + Unpack the data from the loaded file. + + Parameters: + data: the data to unpack + + Returns: + the unpacked data + """ + return data + + +class MemMapDataset(GeneralStructure): + """ + Dataset structure for memory-mapped numpy arrays and props.pkl files. + """ + + _ext = ".mmap" + _extra_files = ["props.pkl"] + + @property + def load_fn(self): + return np.memmap + + def save_preprocess(self, preprocess_path, data_keys, data_dict, extra_data_keys, extra_data_types) -> List[str]: + local_paths = [] + for key in data_keys: + local_path = self.join_and_ext(preprocess_path, key) + out = np.memmap(local_path, mode="w+", dtype=data_dict[key].dtype, shape=data_dict[key].shape) + out[:] = data_dict.pop(key)[:] + out.flush() + local_paths.append(local_path) + + # save smiles and subset + local_path = p_join(preprocess_path, "props.pkl") + + # assert that (required) pkl keys are present in data_dict + assert all([key in data_dict.keys() for key in extra_data_keys]) + + # store unique and inverse indices for str-based pkl keys + for key in extra_data_keys: + if extra_data_types[key] == str: + data_dict[key] = np.unique(data_dict[key], return_inverse=True) + + with open(local_path, "wb") as f: + pkl.dump(data_dict, f) + + local_paths.append(local_path) + return local_paths + + def load_extra_files(self, data, preprocess_path, data_keys, pkl_data_keys, overwrite): + filename = p_join(preprocess_path, "props.pkl") + pull_locally(filename, overwrite=overwrite) + with open(filename, "rb") as f: + tmp = pkl.load(f) + all_pkl_keys = set(tmp.keys()) - set(data_keys) + # assert required pkl_keys are present in all_pkl_keys + assert all([key in all_pkl_keys for key in pkl_data_keys]) + for key in all_pkl_keys: + x = tmp.pop(key) + if len(x) == 2: + data[key] = x[0][x[1]] + else: + data[key] = x + return data + + +class ZarrDataset(GeneralStructure): + """ + Dataset structure for zarr files. + """ + + _ext = ".zip" + _extra_files = ["metadata.zip"] + _zarr_version = 2 + + @property + def load_fn(self): + return zarr.open + + def unpack(self, data): + return data[:] + + def save_preprocess(self, preprocess_path, data_keys, data_dict, extra_data_keys, extra_data_types) -> List[str]: + # os.makedirs(p_join(ds.root, "zips", ds.__name__), exist_ok=True) + local_paths = [] + for key, value in data_dict.items(): + if key not in data_keys: + continue + zarr_path = self.join_and_ext(preprocess_path, key) + value = data_dict.pop(key) + z = zarr.open( + zarr.storage.ZipStore(zarr_path), + "w", + zarr_version=self._zarr_version, + shape=value.shape, + dtype=value.dtype, + ) + z[:] = value[:] + local_paths.append(zarr_path) + # if key in attrs: + # z.attrs.update(attrs[key]) + + metadata = p_join(preprocess_path, "metadata.zip") + + group = zarr.group(zarr.storage.ZipStore(metadata)) + + for key in extra_data_keys: + if extra_data_types[key] == str: + data_dict[key] = np.unique(data_dict[key], return_inverse=True) + + for key, value in data_dict.items(): + # sub=group.create_group(key) + if key in ["name", "subset"]: + data = group.create_dataset(key, shape=value[0].shape, dtype=value[0].dtype) + data[:] = value[0][:] + data2 = group.create_dataset(key + "_ptr", shape=value[1].shape, dtype=np.int32) + data2[:] = value[1][:] + else: + data = group.create_dataset(key, shape=value.shape, dtype=value.dtype) + data[:] = value[:] + local_paths.append(metadata) + return local_paths + + def load_extra_files(self, data, preprocess_path, data_keys, pkl_data_keys, overwrite): + filename = self.join_and_ext(preprocess_path, "metadata") + pull_locally(filename, overwrite=overwrite) + tmp = self.load_fn(filename) + all_pkl_keys = set(tmp.keys()) - set(data_keys) + # assert required pkl_keys are present in all_pkl_keys + assert all([key in all_pkl_keys for key in pkl_data_keys]) + for key in all_pkl_keys: + if key not in pkl_data_keys: + data[key] = tmp[key][:][tmp[key][:]] + else: + data[key] = tmp[key][:] + return data + + # TODO: checksum , maybe convert to archive instead of zips diff --git a/openqdc/methods/atom_energies.py b/openqdc/methods/atom_energies.py index fed41dc4..523ff171 100644 --- a/openqdc/methods/atom_energies.py +++ b/openqdc/methods/atom_energies.py @@ -1,6 +1,6 @@ import ast import pkgutil -from typing import Tuple +from typing import Dict, Tuple import numpy as np from loguru import logger @@ -18,19 +18,15 @@ atom_energy_collection = {k.lower(): v for k, v in atom_energy_collection.items()} -def to_e_matrix(atom_energies: dict) -> np.ndarray: +def to_e_matrix(atom_energies: Dict) -> np.ndarray: """ Get the matrix of isolated atom energies for a dict of non-null values calculates - Parameters - ---------- - atom_energies: dict - Dict of energies computed for a given QM method. - Keys are pairs of (atom, charge) and values are energy values + Parameters: + atom_energies: Dict of energies computed for a given QM method. + Keys are pairs of (atom, charge) and values are energy values - Returns - ------- - np.ndarray of shape (MAX_ATOMIC_NUMBER, 2 * MAX_CHARGE + 1) + Returns: np.ndarray of shape (MAX_ATOMIC_NUMBER, 2 * MAX_CHARGE + 1) Matrix containing the isolated atom energies for each atom and charge written in the form: | | -2 | -1 | 0 | +1 | +2 | <- charges diff --git a/openqdc/utils/download_api.py b/openqdc/utils/download_api.py index c96f3d91..c73c752d 100644 --- a/openqdc/utils/download_api.py +++ b/openqdc/utils/download_api.py @@ -14,7 +14,9 @@ import gdown import requests import tqdm -from aiohttp import ClientTimeout + +# from aiohttp import ClientTimeout +from dotenv import load_dotenv from fsspec import AbstractFileSystem from fsspec.callbacks import TqdmCallback from fsspec.implementations.local import LocalFileSystem @@ -27,25 +29,39 @@ @dataclass class FileSystem: """ - A class to handle file system operations + A basic class to handle file system operations """ public_endpoint: Optional[AbstractFileSystem] = None private_endpoint: Optional[AbstractFileSystem] = None local_endpoint: AbstractFileSystem = LocalFileSystem() + def __init__(self): + load_dotenv() # load environment variables from .env + self.KEY = os.getenv("CLOUDFARE_KEY", None) + self.SECRET = os.getenv("CLOUDFARE_SECRET", None) + @property def public(self): + """ + Return the public remote filesystem with read permission + """ self.connect() return self.public_endpoint @property def private(self): + """ + Return the private remote filesystem with write permission + """ self.connect() return self.private_endpoint @property def local(self): + """ + Return the local filesystem + """ return self.local_endpoint @property @@ -57,23 +73,29 @@ def is_connected(self): def connect(self): """ - Attempt connection to the public and private endpoints + Attempt connection to the public and private remote endpoints """ if not self.is_connected: with warnings.catch_warnings(): warnings.simplefilter("ignore") # No quota warning self.public_endpoint = self.get_default_endpoint("public") self.private_endpoint = self.get_default_endpoint("private") - self.public_endpoint.client_kwargs = {"timeout": ClientTimeout(total=3600, connect=1000)} + # self.public_endpoint.client_kwargs = {"timeout": ClientTimeout(total=3600, connect=1000)} def get_default_endpoint(self, endpoint: str) -> AbstractFileSystem: """ Return a default endpoint for the given str [public, private] """ if endpoint == "private": - return fsspec.filesystem("gs") + return fsspec.filesystem( + "s3", + key=self.KEY, + secret=self.SECRET, + endpoint_url=ioqdc.request_s3fs_config()["endpoint_url"], + ) elif endpoint == "public": - return fsspec.filesystem("https") + # return fsspec.filesystem("https") + return fsspec.filesystem("s3", **ioqdc.request_s3fs_config()) else: return self.local_endpoint diff --git a/openqdc/utils/io.py b/openqdc/utils/io.py index 5e039960..08f69e1a 100644 --- a/openqdc/utils/io.py +++ b/openqdc/utils/io.py @@ -3,6 +3,8 @@ import json import os import pickle as pkl + +# from os.path import join as p_join from typing import Dict, List, Optional import fsspec @@ -23,6 +25,12 @@ "~/.cache/openqdc" if "OPENQDC_CACHE_DIR" not in os.environ else os.path.normpath(os.environ["OPENQDC_CACHE_DIR"]) ) +_OPENQDC_DOWNLOAD_API = { + "s3": "/openqdc/v1", + # "https" : "https://storage.openqdc.org/v1", + "gs": "https://storage.googleapis.com/qmdata-public/openqdc", +} + def set_cache_dir(d): r""" @@ -54,9 +62,11 @@ def get_remote_cache(write_access=False) -> str: Returns the entry point based on the write access. """ if write_access: - remote_cache = "gs://qmdata-public/openqdc" + remote_cache = "openqdc/v1" # "gs://qmdata-public/openqdc" + # remote_cache = "gs://qmdata-public/openqdc" else: - remote_cache = "https://storage.googleapis.com/qmdata-public/openqdc" + remote_cache = _OPENQDC_DOWNLOAD_API.get(os.environ.get("OPENQDC_DOWNLOAD_API", "s3")) + # remote_cache = "https://storage.googleapis.com/qmdata-public/openqdc" return remote_cache @@ -78,6 +88,7 @@ def pull_locally(local_path, overwrite=False): """ Retrieve file from remote gs path or local cache """ + remote_path = local_path.replace(get_local_cache(), get_remote_cache()) os.makedirs(os.path.dirname(local_path), exist_ok=True) if not os.path.exists(local_path) or overwrite: @@ -85,6 +96,15 @@ def pull_locally(local_path, overwrite=False): return local_path +def request_s3fs_config(): + import httpx + + response = httpx.get("https://storage.openqdc.org/config.json") + response.raise_for_status() + config = response.json() + return config + + def copy_exists(local_path): remote_path = local_path.replace(get_local_cache(), get_remote_cache()) return os.path.exists(local_path) or API.exists(remote_path) @@ -150,8 +170,8 @@ def load_hdf5_file(hdf5_file_path: str): # inorder to enable multiprocessing: # https://github.com/fsspec/gcsfs/issues/379#issuecomment-839929801 - fsspec.asyn.iothread[0] = None - fsspec.asyn.loop[0] = None + # fsspec.asyn.iothread[0] = None + # fsspec.asyn.loop[0] = None return file @@ -177,7 +197,7 @@ def load_xyz(path): return MolFromXYZFile(path) -def dict_to_atoms(d: dict, ext: bool = False, energy_method: int = 0) -> Atoms: +def dict_to_atoms(d: Dict, ext: bool = False, energy_method: int = 0) -> Atoms: """ Converts dictionary to ase atoms object diff --git a/openqdc/utils/package_utils.py b/openqdc/utils/package_utils.py index 990f6cb3..e1381dad 100644 --- a/openqdc/utils/package_utils.py +++ b/openqdc/utils/package_utils.py @@ -1,3 +1,4 @@ +# from openFF package import importlib from functools import wraps from typing import Any, Callable, TypeVar diff --git a/openqdc/utils/preprocess.py b/openqdc/utils/preprocess.py deleted file mode 100644 index 1171a68c..00000000 --- a/openqdc/utils/preprocess.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Dataset preprocessing.""" - -import click -import numpy as np -from loguru import logger - -from openqdc import AVAILABLE_DATASETS - -options = list(AVAILABLE_DATASETS.values()) -options_map = {d.__name__.lower(): d for d in options} - - -@click.command() -@click.option("--dataset", "-d", type=str, default="ani1", help="Dataset name or index.") -@click.option("--upload", "-u", type=bool, default=False, help="Try to upload it to the remote storage.") -def preprocess(dataset, upload): - if dataset not in options_map: - dataset_id = int(dataset) - data_class = options[dataset_id] - else: - data_class = options_map[dataset] - - data_class.no_init().preprocess(upload=upload, overwrite=True) - data = data_class() - logger.info(f"Preprocessing {data.__name__}") - - n = len(data) - for i in np.random.choice(n, 3, replace=False): - x = data[i] - print(x.name, x.subset, end=" ") - for k in x: - if isinstance(x[k], np.ndarray): - print(k, x[k].shape, end=" ") - print() - - -if __name__ == "__main__": - preprocess() diff --git a/openqdc/utils/regressor.py b/openqdc/utils/regressor.py index 1d3e50ad..0c23d9b4 100644 --- a/openqdc/utils/regressor.py +++ b/openqdc/utils/regressor.py @@ -7,8 +7,6 @@ import pandas as pd from loguru import logger -SubSampleFrac = Union[float, int] - def non_nan_idxs(array): """ @@ -24,7 +22,18 @@ class Solver(ABC): @staticmethod @abstractmethod - def solve(X, Y): + def solve(X: np.ndarray, Y: np.ndarray) -> Tuple[np.ndarray, Optional[np.ndarray]]: + """ + Main method to solve the regression problem. + Must be implemented in all the subclasses. + + Parameters: + X: Input features of shape (n_samples, n_species) + Y: Target values of shape (n_samples,) (energy values for the regression) + + Returns: + Tuple of predicted values and the estimated uncertainty. + """ pass def __call__(self, X, Y): @@ -38,7 +47,26 @@ def __repr__(self): class Regressor: - """Regressor class for preparing and solving regression problem for isolated atom energies.""" + """ + Regressor class for preparing and solving regression problem for isolated atom energies. + A isolated atom energy regression problem is defined as:\n + X = [n_samples, n_species] (number of atoms of each species per sample)\n + Y = [n_samples, ] (energies)\n + The regression problem is solved by solving the linear system X E0 = Y. + + Example: + For a sytem of 2 samples (H20, CH4)\n + n_species = 3, n_samples = 2\n + H20 = 2H , 1O -> X = [2, 1, 0]\n + CH4 = 4C, 1H -> X = [1, 0, 4]\n + X = [[2, 1, 0], + [ 1, 0, 4]]\n + Y = [[10, 20]]\n + X E0 = Y\n + Linear system to solve\n + [[2 eH, 1 eO, 0 eC], + [ 1 eH, 0 eO, 4 eC]] = [[10, 20]] + """ solver: Solver @@ -49,27 +77,29 @@ def __init__( position_idx_range: np.ndarray, solver_type: str = "linear", stride: int = 1, - subsample: Optional[SubSampleFrac] = None, + subsample: Optional[Union[float, int]] = None, remove_nan: bool = True, - *args, - **kwargs, + *args: any, + **kwargs: any, ): """ - Parameters - ---------- - energies - numpy array of energies in the shape (n_samples, n_energy_methods) - atomic_numbers - numpy array of atomic numbers in the shape (n_atoms,) - position_idx_range - array of shape (n_samples, 2) containing the start and end indices of the atoms in the dataset - stride - Stride to use for the regression. - subsample - Sumsample the dataset. If a float, it is interpreted as a fraction of the dataset to use. - If >1 it is interpreted as the number of samples to use. - remove_nan - Sanitize the dataset by removing energies samples with NaN values. + Regressor class for preparing and solving regression problem for isolated atom energies. + + Parameters: + energies: + numpy array of energies in the shape (n_samples, n_energy_methods) + atomic_numbers: + numpy array of atomic numbers in the shape (n_atoms,) + position_idx_range: + array of shape (n_samples, 2) containing the start and end indices of the atoms in the dataset + solver_type: Type of solver to use. ["linear", "ridge"] + stride: Stride to use for the regression. + subsample: Sumsample the dataset. + If a float, it is interpreted as a fraction of the dataset to use. + If >1 it is interpreted as the number of samples to use. + remove_nan: Sanitize the dataset by removing energies samples with NaN values. + *args: Additional arguments to be passed to the regressor. + **kwargs: Additional keyword arguments to be passed to the regressor. """ self.subsample = subsample self.stride = stride @@ -87,7 +117,19 @@ def __init__( self._post_init() @classmethod - def from_openqdc_dataset(cls, dataset, *args, **kwargs): + def from_openqdc_dataset(cls, dataset: any, *args: any, **kwargs: any) -> "Regressor": + """ + Initialize the regressor object from an openqdc dataset. This is the default method. + *args and and **kwargs are passed to the __init__ method and depends on the specific regressor. + + Parameters: + dataset: openqdc dataset object. + *args: Additional arguments to be passed to the regressor. + **kwargs: Additional keyword arguments to be passed to the regressor. + + Returns: + Instance of the regressor class. + """ energies = dataset.data["energies"] position_idx_range = dataset.data["position_idx_range"] atomic_numbers = dataset.data["atomic_inputs"][:, 0].astype("int32") @@ -116,12 +158,11 @@ def _downsample(self): self.update_hparams({"idxs": idxs}) def _get_solver(self): - if self.solver_type == "linear": + try: + return AVAILABLE_SOLVERS[self.solver_type]() + except KeyError: + logger.warning(f"Unknown solver type {self.solver_type}, defaulting to linear regression.") return LinearSolver() - elif self.solver_type == "ridge": - return RidgeSolver() - logger.warning(f"Unknown solver type {self.solver_type}, defaulting to linear regression.") - return LinearSolver() def _prepare_inputs(self) -> Tuple[np.ndarray, np.ndarray]: logger.info("Preparing inputs for regression.") @@ -137,6 +178,9 @@ def _prepare_inputs(self) -> Tuple[np.ndarray, np.ndarray]: self.y = B def solve(self): + """ + Solve the regression problem and return the predicted isolated energies and the estimated uncertainty. + """ logger.info(f"Solving regression with {self.solver}.") E0_list, cov_list = [], [] for energy_idx in range(self.y.shape[1]): @@ -157,6 +201,11 @@ def __call__(self): def atom_standardization(X, y): + """ + Standardize the energies and the atom counts. + This will make the calculated uncertainty more + meaningful. + """ X_norm = X.sum() X = X / X_norm y = y / X_norm @@ -165,7 +214,14 @@ def atom_standardization(X, y): class LinearSolver(Solver): - _regr_str = "LinearRegression" + """ + Linear regression solver. + + Note: + No Uncertainty associated as it is quite small. + """ + + _regr_str = "linear" @staticmethod def solve(X, y): @@ -175,7 +231,11 @@ def solve(X, y): class RidgeSolver(Solver): - _regr_str = "RidgeRegression" + """ + Ridge regression solver. + """ + + _regr_str = "ridge" @staticmethod def solve(X, y): @@ -189,3 +249,10 @@ def solve(X, y): cov = np.sqrt(sigma2 * np.einsum("ij,kj,kl,li->i", Ainv, X, X, Ainv)) mean = mean + y_mean.reshape([-1]) return mean, cov + + +AVAILABLE_SOLVERS = { + cls._regr_str: cls + for str_name, cls in globals().items() + if isinstance(cls, type) and issubclass(cls, Solver) and str_name != "Solver" # Exclude the base class +} diff --git a/openqdc/utils/units.py b/openqdc/utils/units.py index d8613a58..898faf8a 100644 --- a/openqdc/utils/units.py +++ b/openqdc/utils/units.py @@ -1,11 +1,14 @@ """ -Unit conversion utils. +Units conversion utilities module. -Energy units: - ["kcal/mol", "kj/mol", "hartree", "ev"] +Available Energy units: + ["kcal/mol", "kj/mol", "hartree", "ev" "mev", "ryd] -Distance units: +Available Distance units: ["ang", "nm", "bohr"] + +Available Force units: + Combinations between Energy and Distance units """ from enum import Enum, unique @@ -40,7 +43,16 @@ class EnergyTypeConversion(ConversionEnum, StrEnum): MEV = "mev" RYD = "ryd" - def to(self, energy: "EnergyTypeConversion"): + def to(self, energy: "EnergyTypeConversion") -> Callable[[float], float]: + """ + Get the conversion function to convert the energy to the desired units. + + Parameters: + energy: energy unit to convert to + + Returns: + Callable to convert the distance to the desired units + """ return get_conversion(str(self), str(energy)) @@ -54,7 +66,17 @@ class DistanceTypeConversion(ConversionEnum, StrEnum): NM = "nm" BOHR = "bohr" - def to(self, distance: "DistanceTypeConversion", fraction: bool = False): + def to(self, distance: "DistanceTypeConversion", fraction: bool = False) -> Callable[[float], float]: + """ + Get the conversion function to convert the distance to the desired units. + + Parameters: + distance: distance unit to convert to + fraction: whether it is distance^1 or distance^-1 + + Returns: + callable to convert the distance to the desired units + """ return get_conversion(str(self), str(distance)) if not fraction else get_conversion(str(distance), str(self)) @@ -91,33 +113,32 @@ def __init__(self, energy: EnergyTypeConversion, distance: DistanceTypeConversio def __str__(self): return f"{self.energy}/{self.distance}" - def to(self, energy: EnergyTypeConversion, distance: DistanceTypeConversion): + def to(self, energy: EnergyTypeConversion, distance: DistanceTypeConversion) -> Callable[[float], float]: + """ + Get the conversion function to convert the force to the desired units. + + Parameters: + energy: energy unit to convert to + distance: distance unit to convert to + + Returns: + callable to convert the distance to the desired units + """ return lambda x: self.distance.to(distance, fraction=True)(self.energy.to(energy)(x)) class Conversion: """ - Conversion from one unit system to another. - - Attributes - ---------- - name - A human-readable name for the conversion - fn: - The callable to compute the conversion + Conversion from one unit system to another defined by a name and a callable """ def __init__(self, in_unit: str, out_unit: str, func: Callable[[float], float]): """ - Parameters - ---------- - in_unit - String defining the units of the current values - out_unit - String defining the target units - func - The callable to compute the conversion + Parameters: + in_unit: String defining the units of the current values + out_unit: String defining the target units + func: The callable to compute the conversion """ name = "convert_" + in_unit.lower().strip() + "_to_" + out_unit.lower().strip() @@ -129,11 +150,20 @@ def __init__(self, in_unit: str, out_unit: str, func: Callable[[float], float]): self.fn = func def __call__(self, x): - """Convert measure""" return self.fn(x) -def get_conversion(in_unit: str, out_unit: str): +def get_conversion(in_unit: str, out_unit: str) -> Callable[[float], float]: + """ + Utility function to get the conversion function between two units. + + Parameters: + in_unit : The input unit + out_unit : The output unit + + Returns: + The conversion function + """ name = "convert_" + in_unit.lower().strip() + "_to_" + out_unit.lower().strip() if in_unit.lower().strip() == out_unit.lower().strip(): return lambda x: x @@ -142,6 +172,8 @@ def get_conversion(in_unit: str, out_unit: str): return CONVERSION_REGISTRY[name] +# Conversion definitions + # ev conversion Conversion("ev", "kcal/mol", lambda x: x * 23.0605) Conversion("ev", "hartree", lambda x: x * 0.0367493) diff --git a/pyproject.toml b/pyproject.toml index 43f414b8..d5e6a002 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,10 @@ dependencies = [ "ase" , "gdown", "h5py >= 3.8.0" , - "dscribe" + "dscribe", + "zarr", + "python-dotenv", + "s3fs", ] diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..0718b5fb --- /dev/null +++ b/pytest.ini @@ -0,0 +1,8 @@ +[pytest] +tmp_path_retention_policy = none +filterwarnings = + ignore::DeprecationWarning + ignore::UserWarning + +markers = + download: tests for datasets downloading diff --git a/tests/test_download.py b/tests/test_download.py new file mode 100644 index 00000000..dd53d405 --- /dev/null +++ b/tests/test_download.py @@ -0,0 +1,15 @@ +from os.path import join as p_join +from pathlib import Path + +import pytest + +from openqdc.datasets import QM7 + + +@pytest.mark.download +def test_API_download(tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + ds = QM7(cache_dir=tmp_path) + for filename in ["energies.mmap", "position_idx_range.mmap", "atomic_inputs.mmap", "props.pkl"]: + assert (Path(p_join(tmp_path, ds.preprocess_path, filename))).exists() + monkeypatch.undo()