From cef94fe18547de7df14fb81aee0e1b51c67fb4da Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 6 Nov 2023 16:09:24 +0000 Subject: [PATCH] Automated Docs Update --- docs/CONTRIBUTING.doctree | Bin 0 -> 42864 bytes docs/CONTRIBUTING.html | 256 +++++ docs/CONTRIBUTING.rst | 143 +++ docs/README.doctree | Bin 0 -> 142701 bytes docs/README.html | 562 ++++++++++ docs/README.rst | 504 +++++++++ docs/_sources/CONTRIBUTING.rst.txt | 143 +++ docs/_sources/README.rst.txt | 504 +++++++++ docs/_sources/astartes.rst.txt | 16 +- .../astartes.samplers.extrapolation.rst.txt | 61 ++ .../astartes.samplers.interpolation.rst.txt | 37 + docs/_sources/astartes.samplers.rst.txt | 67 +- docs/_sources/astartes.utils.rst.txt | 61 ++ docs/_sources/index.rst.txt | 4 +- docs/_sources/modules.rst.txt | 1 - docs/_sources/sklearn_to_astartes.rst.txt | 180 ++++ docs/_sources/test.functional.rst.txt | 29 + docs/_sources/test.regression.rst.txt | 21 + docs/_sources/test.rst.txt | 20 + docs/_sources/test.unit.rst.txt | 19 + .../test.unit.samplers.extrapolative.rst.txt | 61 ++ .../test.unit.samplers.interpolative.rst.txt | 37 + docs/_sources/test.unit.samplers.rst.txt | 19 + docs/_sources/test.unit.utils.rst.txt | 37 + .../_sphinx_javascript_frameworks_compat.js | 123 +++ docs/_static/sphinx_highlight.js | 154 +++ docs/astartes.doctree | Bin 0 -> 120192 bytes docs/astartes.html | 388 +++++++ docs/astartes.rst | 38 + docs/astartes.samplers.doctree | Bin 0 -> 22754 bytes docs/astartes.samplers.extrapolation.doctree | Bin 0 -> 56122 bytes docs/astartes.samplers.extrapolation.html | 334 ++++++ docs/astartes.samplers.extrapolation.rst | 61 ++ docs/astartes.samplers.html | 272 +++++ docs/astartes.samplers.interpolation.doctree | Bin 0 -> 16486 bytes docs/astartes.samplers.interpolation.html | 181 ++++ docs/astartes.samplers.interpolation.rst | 37 + docs/astartes.samplers.rst | 30 + docs/astartes.utils.doctree | Bin 0 -> 136339 bytes docs/astartes.utils.html | 527 ++++++++++ docs/astartes.utils.rst | 61 ++ docs/environment.pickle | Bin 0 -> 1163609 bytes docs/genindex.html | 965 ++++++++++++++++++ docs/index.doctree | Bin 0 -> 4622 bytes docs/index.html | 184 ++++ docs/modules.doctree | Bin 0 -> 2750 bytes docs/modules.html | 189 ++++ docs/modules.rst | 8 + docs/objects.inv | Bin 0 -> 2215 bytes docs/py-modindex.html | 361 +++++++ docs/search.html | 131 +++ docs/searchindex.js | 1 + docs/sklearn_to_astartes.doctree | Bin 0 -> 32206 bytes docs/sklearn_to_astartes.html | 276 +++++ docs/sklearn_to_astartes.rst | 180 ++++ docs/test.doctree | Bin 0 -> 3553 bytes docs/test.functional.doctree | Bin 0 -> 47022 bytes docs/test.functional.html | 298 ++++++ docs/test.functional.rst | 29 + docs/test.html | 220 ++++ docs/test.regression.doctree | Bin 0 -> 17390 bytes docs/test.regression.html | 187 ++++ docs/test.regression.rst | 21 + docs/test.rst | 20 + docs/test.unit.doctree | Bin 0 -> 3589 bytes docs/test.unit.html | 202 ++++ docs/test.unit.rst | 19 + docs/test.unit.samplers.doctree | Bin 0 -> 3710 bytes docs/test.unit.samplers.extrapolative.doctree | Bin 0 -> 72599 bytes docs/test.unit.samplers.extrapolative.html | 365 +++++++ docs/test.unit.samplers.extrapolative.rst | 61 ++ docs/test.unit.samplers.html | 249 +++++ docs/test.unit.samplers.interpolative.doctree | Bin 0 -> 35450 bytes docs/test.unit.samplers.interpolative.html | 245 +++++ docs/test.unit.samplers.interpolative.rst | 37 + docs/test.unit.samplers.rst | 19 + docs/test.unit.utils.doctree | Bin 0 -> 27782 bytes docs/test.unit.utils.html | 218 ++++ docs/test.unit.utils.rst | 37 + 79 files changed, 9447 insertions(+), 63 deletions(-) create mode 100644 docs/CONTRIBUTING.doctree create mode 100644 docs/CONTRIBUTING.html create mode 100644 docs/CONTRIBUTING.rst create mode 100644 docs/README.doctree create mode 100644 docs/README.html create mode 100644 docs/README.rst create mode 100644 docs/_sources/CONTRIBUTING.rst.txt create mode 100644 docs/_sources/README.rst.txt create mode 100644 docs/_sources/astartes.samplers.extrapolation.rst.txt create mode 100644 docs/_sources/astartes.samplers.interpolation.rst.txt create mode 100644 docs/_sources/astartes.utils.rst.txt create mode 100644 docs/_sources/sklearn_to_astartes.rst.txt create mode 100644 docs/_sources/test.functional.rst.txt create mode 100644 docs/_sources/test.regression.rst.txt create mode 100644 docs/_sources/test.rst.txt create mode 100644 docs/_sources/test.unit.rst.txt create mode 100644 docs/_sources/test.unit.samplers.extrapolative.rst.txt create mode 100644 docs/_sources/test.unit.samplers.interpolative.rst.txt create mode 100644 docs/_sources/test.unit.samplers.rst.txt create mode 100644 docs/_sources/test.unit.utils.rst.txt create mode 100644 docs/_static/_sphinx_javascript_frameworks_compat.js create mode 100644 docs/_static/sphinx_highlight.js create mode 100644 docs/astartes.doctree create mode 100644 docs/astartes.html create mode 100644 docs/astartes.rst create mode 100644 docs/astartes.samplers.doctree create mode 100644 docs/astartes.samplers.extrapolation.doctree create mode 100644 docs/astartes.samplers.extrapolation.html create mode 100644 docs/astartes.samplers.extrapolation.rst create mode 100644 docs/astartes.samplers.html create mode 100644 docs/astartes.samplers.interpolation.doctree create mode 100644 docs/astartes.samplers.interpolation.html create mode 100644 docs/astartes.samplers.interpolation.rst create mode 100644 docs/astartes.samplers.rst create mode 100644 docs/astartes.utils.doctree create mode 100644 docs/astartes.utils.html create mode 100644 docs/astartes.utils.rst create mode 100644 docs/environment.pickle create mode 100644 docs/genindex.html create mode 100644 docs/index.doctree create mode 100644 docs/index.html create mode 100644 docs/modules.doctree create mode 100644 docs/modules.html create mode 100644 docs/modules.rst create mode 100644 docs/objects.inv create mode 100644 docs/py-modindex.html create mode 100644 docs/search.html create mode 100644 docs/searchindex.js create mode 100644 docs/sklearn_to_astartes.doctree create mode 100644 docs/sklearn_to_astartes.html create mode 100644 docs/sklearn_to_astartes.rst create mode 100644 docs/test.doctree create mode 100644 docs/test.functional.doctree create mode 100644 docs/test.functional.html create mode 100644 docs/test.functional.rst create mode 100644 docs/test.html create mode 100644 docs/test.regression.doctree create mode 100644 docs/test.regression.html create mode 100644 docs/test.regression.rst create mode 100644 docs/test.rst create mode 100644 docs/test.unit.doctree create mode 100644 docs/test.unit.html create mode 100644 docs/test.unit.rst create mode 100644 docs/test.unit.samplers.doctree create mode 100644 docs/test.unit.samplers.extrapolative.doctree create mode 100644 docs/test.unit.samplers.extrapolative.html create mode 100644 docs/test.unit.samplers.extrapolative.rst create mode 100644 docs/test.unit.samplers.html create mode 100644 docs/test.unit.samplers.interpolative.doctree create mode 100644 docs/test.unit.samplers.interpolative.html create mode 100644 docs/test.unit.samplers.interpolative.rst create mode 100644 docs/test.unit.samplers.rst create mode 100644 docs/test.unit.utils.doctree create mode 100644 docs/test.unit.utils.html create mode 100644 docs/test.unit.utils.rst diff --git a/docs/CONTRIBUTING.doctree b/docs/CONTRIBUTING.doctree new file mode 100644 index 0000000000000000000000000000000000000000..6785b94ad8f772ecdb33125cec0f92362de279fb GIT binary patch literal 42864 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 eN-ncZn~ICmK!z@pI7592Z2s{+Nvql}7ymz$ + + + + + + Contributing & Developer Notes — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Contributing & Developer Notes

+

Pull Requests, Bug Reports, and all Contributions are welcome, encouraged, and appreciated! +Please use the appropriate issue or pull request template when making a contribution to help the maintainers get it merged quickly.

+

We make use of the GitHub Discussions page to go over potential features to add. +Please feel free to stop by if you are looking for something to develop or have an idea for a useful feature!

+

When submitting a PR, please mark your PR with the “PR Ready for Review” label when you are finished making changes so that the GitHub actions bots can work their magic!

+
+

Developer Install

+

To contribute to the astartes source code, start by forking and then cloning the repository (i.e. git clone git@github.com:YourUsername/astartes.git) and then inside the repository run pip install -e .[dev]. This will set you up with all the required dependencies to run astartes and conform to our formatting standards (black and isort), which you can configure to run automatically in VSCode like this.

+
+

Warning +Windows (PowerShell) and MacOS Catalina or newer (zsh) require double quotes around the [] characters (i.e. pip install "astartes[dev]")

+
+
+
+

Version Checking

+

astartes uses pyproject.toml to specify all metadata, but the version is also specified in astartes/__init__.py (via __version__) for backwards compatibility with Python 3.7. +To check which version of astartes you have installed, you can run python -c "import astartes; print(astartes.__version__)" on Python 3.7 or `python -c “from importlib.metadata import version; version(‘astartes’)” on Python 3.8 or newer.

+
+
+

Testing

+

All of the tests in astartes are written using the built-in python unittest module (to allow running without pytest) but we highly recommend using pytest. +To execute the tests from the astartes repository, simply type pytest after running the developer install (or alternately, pytest -v for a more helpful output). +On GitHub, we use actions to run the tests on every Pull Request and on a nightly basis (look in .github/workflows for more information). +These tests include unit tests, functional tests, and regression tests.

+
+
+

Adding New Samplers

+

Adding a new sampler should extend the abstract_sampler.py abstract base class. +Each subclass should override the _sample method with its own algorithm for data partitioning and optionally the _before_sample method to perform any data validation.

+

All samplers in astartes are classified as one of two types: extrapolative or interpolative. +Extrapolative samplers work by clustering data into groups (which are then partitioned into train/validation/test to enforce extrapolation) whereas interpolative samplers provide an exact order in which samples should be moved into the training set.

+

When actually implemented, this means that extrapolative samplers should set the self._samples_clusters attribute and interpolative samplers should set the self._samples_idxs attribute.

+

New samplers can be as simple as a passthrough to another train_test_split, or it can be an original implementation that results in X and y being split into two lists. Take a look at astartes/samplers/interpolation/random_split.py for a basic example!

+

After the sampler has been implemented, add it to __init__.py in in astartes/samplers and it will automatically be unit tested. Additional unit tests to verify that hyperparameters can be properly passed, etc. are also recommended.

+

For historical reasons, and as a guide for any developers who would like add new samplers, below is a running list of samplers which have been considered for addition to asartes but ultimately not added for various reasons.

+
+

Not Implemented Sampling Algorithms

+ + + + + + + + + + + + + + + + + +

Sampler Name

Reasoning

Relevant Link(s)

D-Optimal

Requires a-priori knowledge of the test and train size which does not fit in the astartes framework (samplers are all agnostic to the size of the sets) and it is questionable if the use of the Fischer information matrix is actually meaningful in the context of sampling existing data rather than tuning for ideal data.

The Wikipedia article for optimal design does a good job explaining why this is difficult, and points at some potential alternatives.

Duplex

Requires knowing test and train size before execution, and can only partition data into two sets which would make it incompatible with train_val_test_split.

This implementation in R includes helpful references and a reference implementation.

+
+
+
+

Adding New Featurization Schemes

+

All of the sampling methods implemented in astartes accept arbitrary arrays of numbers and return the sampled groups (with the exception of Scaffold.py). If you have an existing featurization scheme (i.e. take an arbitrary input and turn it into an array of numbers), we would be thrilled to include it in astartes.

+

Adding a new interface should take on this format:

+
from astartes import train_test_split
+
+def train_test_split_INTERFACE(
+    INTERFACE_input,
+    INTERFACE_ARGS,
+    y: np.array = None,
+    labels: np.array = None,
+    test_size: float = 0.25,
+    train_size: float = 0.75,
+    splitter: str = 'random',
+    hopts: dict = {},
+    INTERFACE_hopts: dict = {},
+):
+    # turn the INTERFACE_input into an input X
+    # based on INTERFACE ARGS where INTERFACE_hopts
+    # specifies additional behavior
+    X = []
+
+    # call train test split with this input
+    return train_test_split(
+        X,
+        y=y,
+        labels=labels,
+        test_size=test_size,
+        train_size=train_size,
+        splitter=splitter,
+        hopts=hopts,
+    )
+
+
+

If possible, we would like to also add an example Jupyter Notebook with any new interface to demonstrate to new users how it functions. See our other examples in the examples directory.

+

Contact @JacksonBurns if you need assistance adding an existing workflow to astartes. If this featurization scheme requires additional dependencies to function, we may add it as an additional extra package in the same way that molecules in installed.

+
+
+

The train_val_test_split Function

+

train_val_test_split is the workhorse function of astartes. +It is responsible for instantiating the sampling algorithm, partitioning the data into training, validation, and testing, and then returning the requested results while also keeping an eye on data types. +Under the hood, train_test_split is just calling train_val_test_split with val_size set to 0.0. +For more information on how it works, check out the inline documentation in astartes/main.py.

+
+
+

Development Philosophy

+

The developers of astartes prioritize (1) reproducibility, (2) flexibility, and (3) maintainability.

+
    +
  1. All versions of astartes 1.x should produce the same results across all platforms, so we have thorough unit and regression testing run on a continuous basis.

  2. +
  3. We specify as few dependencies as possible with the loosest possible dependency requirements, which allows integrating astartes with other tools more easily.

    +
      +
    • Dependencies which introduce a lot of requirements and/or specific versions of requirements are shuffled into the extras_require to avoid weighing down the main package.

    • +
    • Compatibility with all versions of modern Python is achieved by not tightly specifying version numbers as well as by regression testing across all versions.

    • +
    +
  4. +
  5. We follow DRY (Don’t Repeat Yourself) principles to avoid code duplication and decrease maintainence burden, have near-perfect test coverage, and enforce consistent formatting style in the source code.

    +
      +
    • Inline comments are critical for maintainability - at the time of writing, astartes has 1 comment line for every 2 lines of source code.

    • +
    +
  6. +
+
+
+
+

JOSS Branch

+

astartes corresponding JOSS paper is stored in this repository on a separate branch. You can find paper.md on the aptly named joss-paper branch.

+

Note for Maintainers: To push changes from the main branch into the joss-paper branch, run the Update JOSS Branch workflow.

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/CONTRIBUTING.rst b/docs/CONTRIBUTING.rst new file mode 100644 index 00000000..677944a2 --- /dev/null +++ b/docs/CONTRIBUTING.rst @@ -0,0 +1,143 @@ + +Contributing & Developer Notes +------------------------------ + +Pull Requests, Bug Reports, and all Contributions are welcome, encouraged, and appreciated! +Please use the appropriate `issue `_ or `pull request `_ template when making a contribution to help the maintainers get it merged quickly. + +We make use of `the GitHub Discussions page `_ to go over potential features to add. +Please feel free to stop by if you are looking for something to develop or have an idea for a useful feature! + +When submitting a PR, please mark your PR with the "PR Ready for Review" label when you are finished making changes so that the GitHub actions bots can work their magic! + +Developer Install +^^^^^^^^^^^^^^^^^ + +To contribute to the ``astartes`` source code, start by forking and then cloning the repository (i.e. ``git clone git@github.com:YourUsername/astartes.git``\ ) and then inside the repository run ``pip install -e .[dev]``. This will set you up with all the required dependencies to run ``astartes`` and conform to our formatting standards (\ ``black`` and ``isort``\ ), which you can configure to run automatically in VSCode `like this `_. + +.. + + **Warning** + Windows (PowerShell) and MacOS Catalina or newer (zsh) require double quotes around the ``[]`` characters (i.e. ``pip install "astartes[dev]"``\ ) + + +Version Checking +^^^^^^^^^^^^^^^^ + +``astartes`` uses ``pyproject.toml`` to specify all metadata, but the version is also specified in ``astartes/__init__.py`` (via ``__version__``\ ) for backwards compatibility with Python 3.7. +To check which version of ``astartes`` you have installed, you can run ``python -c "import astartes; print(astartes.__version__)"`` on Python 3.7 or `python -c "from importlib.metadata import version; version('astartes')" on Python 3.8 or newer. + +Testing +^^^^^^^ + +All of the tests in ``astartes`` are written using the built-in python ``unittest`` module (to allow running without ``pytest``\ ) but we *highly* recommend using ``pytest``. +To execute the tests from the ``astartes`` repository, simply type ``pytest`` after running the developer install (or alternately, ``pytest -v`` for a more helpful output). +On GitHub, we use actions to run the tests on every Pull Request and on a nightly basis (look in ``.github/workflows`` for more information). +These tests include unit tests, functional tests, and regression tests. + +Adding New Samplers +^^^^^^^^^^^^^^^^^^^ + +Adding a new sampler should extend the ``abstract_sampler.py`` abstract base class. +Each subclass should override the ``_sample`` method with its own algorithm for data partitioning and optionally the ``_before_sample`` method to perform any data validation. + +All samplers in ``astartes`` are classified as one of two types: extrapolative or interpolative. +Extrapolative samplers work by clustering data into groups (which are then partitioned into train/validation/test to enforce extrapolation) whereas interpolative samplers provide an exact *order* in which samples should be moved into the training set. + +When actually implemented, this means that extrapolative samplers should set the ``self._samples_clusters`` attribute and interpolative samplers should set the ``self._samples_idxs`` attribute. + +New samplers can be as simple as a passthrough to another ``train_test_split``\ , or it can be an original implementation that results in X and y being split into two lists. Take a look at ``astartes/samplers/interpolation/random_split.py`` for a basic example! + +After the sampler has been implemented, add it to ``__init__.py`` in in ``astartes/samplers`` and it will automatically be unit tested. Additional unit tests to verify that hyperparameters can be properly passed, etc. are also recommended. + +For historical reasons, and as a guide for any developers who would like add new samplers, below is a running list of samplers which have been *considered* for addition to ``asartes`` but ultimately not added for various reasons. + +Not Implemented Sampling Algorithms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - Sampler Name + - Reasoning + - Relevant Link(s) + * - D-Optimal + - Requires *a-priori* knowledge of the test and train size which does not fit in the ``astartes`` framework (samplers are all agnostic to the size of the sets) and it is questionable if the use of the Fischer information matrix is actually meaningful in the context of sampling existing data rather than tuning for ideal data. + - The `Wikipedia article for optimal design `_ does a good job explaining why this is difficult, and points at some potential alternatives. + * - Duplex + - Requires knowing test and train size before execution, and can only partition data into two sets which would make it incompatible with ``train_val_test_split``. + - This `implementation in R `_ includes helpful references and a reference implementation. + + +Adding New Featurization Schemes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All of the sampling methods implemented in ``astartes`` accept arbitrary arrays of numbers and return the sampled groups (with the exception of ``Scaffold.py``\ ). If you have an existing featurization scheme (i.e. take an arbitrary input and turn it into an array of numbers), we would be thrilled to include it in ``astartes``. + +Adding a new interface should take on this format: + +.. code-block:: python + + from astartes import train_test_split + + def train_test_split_INTERFACE( + INTERFACE_input, + INTERFACE_ARGS, + y: np.array = None, + labels: np.array = None, + test_size: float = 0.25, + train_size: float = 0.75, + splitter: str = 'random', + hopts: dict = {}, + INTERFACE_hopts: dict = {}, + ): + # turn the INTERFACE_input into an input X + # based on INTERFACE ARGS where INTERFACE_hopts + # specifies additional behavior + X = [] + + # call train test split with this input + return train_test_split( + X, + y=y, + labels=labels, + test_size=test_size, + train_size=train_size, + splitter=splitter, + hopts=hopts, + ) + +If possible, we would like to also add an example Jupyter Notebook with any new interface to demonstrate to new users how it functions. See our other examples in the ``examples`` directory. + +Contact `@JacksonBurns `_ if you need assistance adding an existing workflow to ``astartes``. If this featurization scheme requires additional dependencies to function, we may add it as an additional *extra* package in the same way that ``molecules`` in installed. + +The ``train_val_test_split`` Function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``train_val_test_split`` is the workhorse function of ``astartes``. +It is responsible for instantiating the sampling algorithm, partitioning the data into training, validation, and testing, and then returning the requested results while also keeping an eye on data types. +Under the hood, ``train_test_split`` is just calling ``train_val_test_split`` with ``val_size`` set to ``0.0``. +For more information on how it works, check out the inline documentation in ``astartes/main.py``. + +Development Philosophy +^^^^^^^^^^^^^^^^^^^^^^ + +The developers of ``astartes`` prioritize (1) reproducibility, (2) flexibility, and (3) maintainability. + + +#. All versions of ``astartes`` ``1.x`` should produce the same results across all platforms, so we have thorough unit and regression testing run on a continuous basis. +#. We specify as *few dependencies as possible* with the *loosest possible* dependency requirements, which allows integrating ``astartes`` with other tools more easily. + + * Dependencies which introduce a lot of requirements and/or specific versions of requirements are shuffled into the ``extras_require`` to avoid weighing down the main package. + * Compatibility with all versions of modern Python is achieved by not tightly specifying version numbers as well as by regression testing across all versions. + +#. We follow DRY (Don't Repeat Yourself) principles to avoid code duplication and decrease maintainence burden, have near-perfect test coverage, and enforce consistent formatting style in the source code. + + * Inline comments are *critical* for maintainability - at the time of writing, ``astartes`` has 1 comment line for every 2 lines of source code. + +JOSS Branch +----------- + +``astartes`` corresponding JOSS paper is stored in this repository on a separate branch. You can find ``paper.md`` on the aptly named ``joss-paper`` branch. + +*Note for Maintainers*\ : To push changes from the ``main`` branch into the ``joss-paper`` branch, run the ``Update JOSS Branch`` workflow. diff --git a/docs/README.doctree b/docs/README.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d311e3aec0997548ca97e52f3b234351e11fb0d7 GIT binary patch literal 142701 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 Vbp!prP;WP3{#nj5dd&P%>IbSy&|v@o literal 0 HcmV?d00001 diff --git a/docs/README.html b/docs/README.html new file mode 100644 index 00000000..eeb87670 --- /dev/null +++ b/docs/README.html @@ -0,0 +1,562 @@ + + + + + + + Online Documentation — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

astartes

+

(as-tar-tees)

+

Train:Validation:Test Algorithmic Sampling for Molecules and Arbitrary Arrays

+
:raw-html-m2r:`<p align=”center”>

<img alt=”astarteslogo” src=”https://raw.githubusercontent.com/JacksonBurns/astartes/main/astartes_logo.png”>

+
+
+

</p>`

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Status Badges

UsageContinuous IntegrationRelease
PyPI - Python VersionReproduce PaperpyOpenSci approved
PyPI - LicenseTest StatusDOI
PyPI - Total DownloadsPyPI conda-forge version
GitHub Repo StarsProject Status: Active – The project has reached a stable, usable state and is being actively developed.
+
+

Online Documentation

+

Follow this link for a nicely-rendered version of this README along with additional tutorials for moving from train_test_split in sklearn to astartes. +Keep reading for a installation guide and links to tutorials!

+
+
+

Installing astartes

+

We recommend installing astartes within a virtual environment, using either venv or conda (or other tools) to simplify dependency management. Python versions 3.7, 3.8, 3.9, 3.10, and 3.11 are supported on all platforms.

+
+

Warning +Windows (PowerShell) and MacOS Catalina or newer (zsh) require double quotes around text using the '[]' characters (i.e. pip install "astartes[molecules]").

+
+
+

pip

+

astartes is available on PyPI and can be installed using pip:

+
    +
  • To include the featurization options for chemical data, use pip install astartes[molecules].

  • +
  • To install only the sampling algorithms, use pip install astartes (this install will have fewer dependencies and may be more readily compatible in environments with existing workflows).

  • +
+
+
+

conda

+

astartes package is also available on conda-forge with this command: conda install -c conda-forge astartes. +To install astartes with support for featurizing molecules, use: conda install -c conda-forge astartes aimsim. +This will download the base astartes package as well as aimsim, which is the backend used for molecular featurization.

+
+
+

Source

+

To install astartes from source for development, see the Contributing & Developer Notes section.

+
+
+
+

Statement of Need

+

Machine learning has sparked an explosion of progress in chemical kinetics, materials science, and many other fields as researchers use data-driven methods to accelerate steps in traditional workflows within some acceptable error tolerance. +To facilitate adoption of these models, there are two important tasks to consider:

+
    +
  1. use a validation set when selecting the optimal hyperparameter for the model and separately use a held-out test set to measure performance on unseen data.

  2. +
  3. evaluate model performance on both interpolative and extrapolative tasks so future users are informed of any potential limitations.

  4. +
+

astartes addresses both of these points by implementing an sklearn-compatible train_val_test_split function. +Additional technical detail is provided below as well as in our companion paper. +For a demo-based explainer using machine learning on a fast food menu, see the astartes Reproducible Notebook published at the United States Research Software Engineers Conference at this page.

+
+

Target Audience

+

astartes is generally applicable to machine learning involving both discovery and inference and model validation. +There are specific functions in astartes for applications in cheminformatics (astartes.molecules) but the methods implemented are general to all numerical data.

+
+
+
+

Quick Start

+

astartes is designed as a drop-in replacement for sklearn‘s train_test_split function (see the sklearn documentation). To switch to astartes, change from sklearn.model_selection import train_test_split to from astartes import train_test_split.

+

Like sklearn, astartes accepts any iterable object as X, y, and labels. +Each will be converted to a numpy array for internal operations, and returned as a numpy array with limited exceptions: if X is a pandas DataFrame, y is a Series, or labels is a Series, astartes will cast it back to its original type including its index and column names.

+
+

Note +The developers recommend passing X, y, and labels as numpy arrays and handling the conversion to and from other types explicitly on your own. Behind-the-scenes type casting can lead to unexpected behavior!

+
+

By default, astartes will split data randomly. Additionally, a variety of algorithmic sampling approaches can be used by specifying the sampler argument to the function (see the Table of Implemented Samplers for a complete list of options and their corresponding references):

+
from sklearn.datasets import load_diabetes
+
+X, y = load_diabetes(return_X_y=True)
+
+X_train, X_test, y_train, y_test = train_test_split(
+  X,  # preferably numpy arrays, but astartes will cast it for you
+  y,
+  sampler = 'kennard_stone',  # any of the supported samplers
+)
+
+
+
+

Note +Extrapolation sampling algorithms will return an additional set of arrays (the cluster labels) which will result in a ValueError: too many values to unpack if not called properly. See the ``split_comparisons` Google colab demo <https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/split_comparisons/split_comparisons.ipynb>`_ for a full explanation.

+
+

That’s all you need to get started with astartes! +The next sections include more examples and some demo notebooks you can try in your browser.

+
+

Example Notebooks

+

Click the badges in the table below to be taken to a live, interactive demo of astartes:

+

To execute these notebooks locally, clone this repository (i.e. git clone https://github.com/JacksonBurns/astartes.git), navigate to the astartes directory, run pip install .[demos], then open and run the notebooks in your preferred editor. +You do not need to execute the cells prefixed with %%capture - they are only present for compatibility with Google Colab.

+
+
+

Withhold Testing Data with train_val_test_split

+

For rigorous ML research, it is critical to withhold some data during training to use a test set. +The model should never see this data during training (unlike the validation set) so that we can get an accurate measurement of its performance.

+

With astartes performing this three-way data split is readily available with train_val_test_split:

+
from astartes import train_val_test_split
+
+X_train, X_val, X_test = train_val_test_split(X, sampler = 'sphere_exclusion')
+
+
+

You can now train your model with X_train, optimize your model with X_val, and measure its performance with X_test.

+
+
+

Evaluate the Impact of Splitting Algorithms on Regression Models

+

For data with many features it can be difficult to visualize how different sampling algorithms change the distribution of data into training, validation, and testing like we do in some of the demo notebooks. +To aid in analyzing the impact of the algorithms, astartes provides generate_regression_results_dict. +This function allows users to quickly evaluate the impact of different splitting techniques on any sklearn-compatible model’s performance. +All results are stored in a nested dictionary ({sampler:{metric:{split:score}}}) format and can be displayed in a neatly formatted table using the optional print_results argument.

+
from sklearn.svm import LinearSVR
+
+from astartes.utils import generate_regression_results_dict as grrd
+
+sklearn_model = LinearSVR()
+results_dict = grrd(
+    sklearn_model,
+    X,
+    y,
+    print_results=True,
+)
+
+         Train       Val      Test
+----  --------  --------  --------
+MAE   1.41522   3.13435   2.17091
+RMSE  2.03062   3.73721   2.40041
+R2    0.90745   0.80787   0.78412
+
+
+

Additional metrics can be passed to generate_regression_results_dict via the additional_metrics argument, which should be a dictionary mapping the name of the metric (as a string) to the function itself, like this:

+
from sklearn.metrics import mean_absolute_percentage_error
+
+add_met = {"mape": mean_absolute_percentage_error}
+
+grrd(sklearn_model, X, y, additional_metric=add_met)
+
+
+

See the docstring for generate_regression_results_dict (with help(generate_regression_results_dict)) for more information.

+
+
+

Using astartes with Categorical Data

+

Any of the implemented sampling algorithms whose hyperparameters allow specifying the metric or distance_metric (effectively 1-metric) can be co-opted to work with categorical data. +Simply encode the data in a format compatible with the sklearn metric of choice and then call astartes with that metric specified:

+
from sklearn.metrics import jaccard_score
+
+X_train, X_test, y_train, y_test = train_test_split(
+  X,
+  y,
+  sampler='kennard_stone',
+  hopts={"metric": jaccard_score},
+)
+
+
+

Other samplers which do not allow specifying a categorical distance metric did not provide a method for doing so in their original inception, though it is possible that they can be adapted for this application. +If you are interested in adding support for categorical metrics to an existing sampler, consider opening a Feature Request!

+
+
+

Access Sampling Algorithms Directly

+

The sampling algorithms implemented in astartes can also be directly accessed and run if it is more useful for your applications. +In the below example, we import the Kennard Stone sampler, use it to partition a simple array, and then retrieve a sample.

+
from astartes.samplers.interpolation import KennardStone
+
+kennard_stone = KennardStone([[1, 2], [3, 4], [5, 6]])
+first_2_samples = kennard_stone.get_sample_idxs(2)
+
+
+

All samplers in astartes implement a _sample() method that is called by the constructor (i.e. greedily) and either a get_sampler_idxs or get_cluster_idxs for interpolative and extrapolative samplers, respectively. +For more detail on the implementaiton and design of samplers in astartes, see the Developer Notes section.

+
+
+
+

Theory and Application of astartes

+

This section of the README details some of the theory behind why the algorithms implemented in astartes are important and some motivating examples. +For a comprehensive walkthrough of the theory and implementation of astartes, follow this link to read the companion paper (freely available and hosted here on GitHub).

+
+

Note +We reference open-access publications wherever possible. For articles locked behind a paywall (denoted with :small_blue_diamond:), we instead suggest reading this Wikipedia page and absolutely not attempting to bypass the paywall.

+
+
+

Rational Splitting Algorithms

+

While much machine learning is done with a random choice between training/validation/test data, an alternative is the use of so-called “rational” splitting algorithms. +These approaches use some similarity-based algorithm to divide data into sets. +Some of these algorithms include Kennard-Stone (Kennard & Stone :small_blue_diamond:), Sphere Exclusion (Tropsha et. al :small_blue_diamond:),as well as the OptiSim as discussed in Applied Chemoinformatics: Achievements and Future Opportunities :small_blue_diamond:. +Some clustering-based splitting techniques have also been incorporated, such as DBSCAN.

+

There are two broad categories of sampling algorithms implemented in astartes: extrapolative and interpolative. +The former will force your model to predict on out-of-sample data, which creates a more challenging task than interpolative sampling. +See the table below for all of the sampling approaches currently implemented in astartes, as well as the hyperparameters that each algorithm accepts (which are passed in with hopts) and a helpful reference for understanding how the hyperparameters work. +Note that random_state is defined as a keyword argument in train_test_split itself, even though these algorithms will use the random_state in their own work. +Do not provide a random_state in the hopts dictionary - it will be overwritten by the random_state you provide for train_test_split (or the default if none is provided).

+
+

Implemented Sampling Algorithms

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Sampler Name

Usage String

Type

Hyperparameters

Reference

Notes

Random

‘random’

Interpolative

shuffle

sklearn train_test_split Documentation

This sampler is a direct passthrough to sklearn‘s train_test_split.

Kennard-Stone

‘kennard_stone’

Interpolative

metric

Original Paper by Kennard & Stone :small_blue_diamond:

Euclidian distance is used by default, as described in the original paper.

Sample set Partitioning based on joint X-Y distances (SPXY)

‘spxy’

Interpolative

distance_metric

Saldhana et. al original paper :small_blue_diamond:

Extension of Kennard Stone that also includes the response when sampling distances.

Mahalanobis Distance Kennard Stone (MDKS)

‘spxy’ (MDKS is derived from SPXY)

Interpolative

none, see Notes

Saptoro et. al original paper

MDKS is SPXY using Mahalanobis distance and can be called by using SPXY with distance_metric="mahalanobis"

Scaffold

‘scaffold’

Extrapolative

include_chirality

Bemis-Murcko Scaffold :small_blue_diamond: as implemented in RDKit

This sampler requires SMILES strings as input (use the molecules subpackage)

Sphere Exclusion

‘sphere_exclusion’

Extrapolative

metric, distance_cutoff

custom implementation

Variation on Sphere Exclusion for arbitrary-valued vectors.

Time Based

‘time_based’

Extrapolative

none

Papers using Time based splitting: Chen et al. :small_blue_diamond:, Sheridan, R. P :small_blue_diamond:, Feinberg et al. :small_blue_diamond:, Struble et al.

This sampler requires labels to be an iterable of either date or datetime objects.

Optimizable K-Dissimilarity Selection (OptiSim)

‘optisim’

Extrapolative

n_clusters, max_subsample_size, distance_cutoff

custom implementation

Variation on OptiSim for arbitrary-valued vectors.

K-Means

‘kmeans’

Extrapolative

n_clusters, n_init

``sklearn KMeans` <https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html>`_

Passthrough to sklearn‘s KMeans.

Density-Based Spatial Clustering of Applications with Noise (DBSCAN)

‘dbscan’

Extrapolative

eps, min_samples, algorithm, metric, leaf_size

``sklearn DBSCAN` <https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html>`_ Documentation

Passthrough to sklearn‘s DBSCAN.

Minimum Test Set Dissimilarity (MTSD)

~

~

upcoming in astartes v1.x

~

~

Restricted Boltzmann Machine (RBM)

~

~

upcoming in astartes v1.x

~

~

Kohonen Self-Organizing Map (SOM)

~

~

upcoming in astartes v1.x

~

~

SPlit Method

~

~

upcoming in astartes v1.x

~

~

+
+
+
+

Domain-Specific Applications

+

Below are some field specific applications of astartes. Interested in adding a new sampling algorithm or featurization approach? See ``CONTRIBUTING.md` <./CONTRIBUTING.md>`_.

+
+

Chemical Data and the astartes.molecules Subpackage

+

Machine Learning is enormously useful in chemistry-related fields due to the high-dimensional feature space of chemical data. +To properly apply ML to chemical data for inference or discovery, it is important to know a model’s accuracy under the two domains. +To simplify the process of partitioning chemical data, astartes implements a pre-built featurizer for common chemistry data formats. +After installing with pip install astartes[molecules] one can import the new train/test splitting function like this: from astartes.molecules import train_test_split_molecules

+

The usage of this function is identical to train_test_split but with the addition of new arguments to control how the molecules are featurized:

+
train_test_split_molecules(
+    molecules=smiles,
+    y=y,
+    test_size=0.2,
+    train_size=0.8,
+    fingerprint="daylight_fingerprint",
+    fprints_hopts={
+        "minPath": 2,
+        "maxPath": 5,
+        "fpSize": 200,
+        "bitsPerHash": 4,
+        "useHs": 1,
+        "tgtDensity": 0.4,
+        "minSize": 64,
+    },
+    sampler="random",
+    random_state=42,
+    hopts={
+        "shuffle": True,
+    },
+)
+
+
+

To see a complete example of using train_test_split_molecules with actual chemical data, take a look in the examples directory and the brief companion paper.

+

Configuration options for the featurization scheme can be found in the documentation for AIMSim though most of the critical configuration options are shown above.

+
+
+
+
+

Reproducibility

+

astartes aims to be completely reproducible across different platforms, Python versions, and dependency configurations - any version of astartes v1.x should result in the exact same splits, always. +To that end, the default behavior of astartes is to use 42 as the random seed and always set it. +Running astartes with the default settings will always produce the exact same results. +We have verified this behavior on Debian Ubuntu, Windows, and Intel Macs from Python versions 3.7 through 3.11 (with appropriate dependencies for each version).

+
+

Known Reproducibility Limitations

+

Inevitably external dependencies of astartes will introduce backwards-incompatible changes. +We continually run regression tests to catch these, and will list all known limitations here:

+
    +
  • sklearn v1.3.0 introduced backwards-incompatible changes in the KMeans sampler that changed how the random initialization affects the results, even given the same random seed. Different version of sklearn will affect the performance of astartes and we recommend including the exact version of scikit-learn and astartes used, when applicable.

  • +
+
+

Note +We are limited in our ability to test on M1 Macs, but from our limited manual testing we achieve perfect reproducbility in all cases except occasionally with KMeans on Apple silicon. +astartes is still consistent between runs on the same platform in all cases, and other samplers are not impacted by this apparent bug.

+
+
+
+
+

How to Cite

+

If you use astartes in your work please use the below citation or the “Cite this repository” button on GitHub:

+
+

BibTeX +@software{burns_jackson_2023_8147205,

+
+
+
author = {Burns, Jackson and

Spiekermann, Kevin and +Bhattacharjee, Himaghna and +Vlachos, Dionisios and +Green, William},

+
+
title = {{Machine Learning Validation via Rational Dataset

Sampling with astartes}},

+
+
+

month = may, +year = 2023, +publisher = {Zenodo}, +version = {1.1.1}, +doi = {10.5281/zenodo.8147205}, +url = {https://doi.org/10.5281/zenodo.8147205}

+
+

}

+
+
+
+

Contributing & Developer Notes

+

See CONTRIBUTING.md for instructions on installing astartes for development, making a contribution, and general guidance on the design of astartes.

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/README.rst b/docs/README.rst new file mode 100644 index 00000000..0baa5f3c --- /dev/null +++ b/docs/README.rst @@ -0,0 +1,504 @@ +.. role:: raw-html-m2r(raw) + :format: html + + +:raw-html-m2r:`

astartes

` + +:raw-html-m2r:`

(as-tar-tees)

` + + +.. raw:: html + +

Train:Validation:Test Algorithmic Sampling for Molecules and Arbitrary Arrays

+ + +:raw-html-m2r:`

+ astarteslogo +

` + + +.. raw:: html + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Status Badges

UsageContinuous IntegrationRelease
PyPI - Python VersionReproduce PaperpyOpenSci approved
PyPI - LicenseTest StatusDOI
PyPI - Total DownloadsPyPI conda-forge version
GitHub Repo StarsProject Status: Active – The project has reached a stable, usable state and is being actively developed.
+
+ + +Online Documentation +-------------------- + +Follow `this link `_ for a nicely-rendered version of this README along with additional tutorials for `moving from train_test_split in sklearn to astartes `_. +Keep reading for a installation guide and links to tutorials! + +Installing ``astartes`` +--------------------------- + +We recommend installing ``astartes`` within a virtual environment, using either ``venv`` or ``conda`` (or other tools) to simplify dependency management. Python versions 3.7, 3.8, 3.9, 3.10, and 3.11 are supported on all platforms. + +.. + + **Warning** + Windows (PowerShell) and MacOS Catalina or newer (zsh) require double quotes around text using the ``'[]'`` characters (i.e. ``pip install "astartes[molecules]"``\ ). + + +``pip`` +^^^^^^^^^^^ + +``astartes`` is available on ``PyPI`` and can be installed using ``pip``\ : + + +* To include the featurization options for chemical data, use ``pip install astartes[molecules]``. +* To install only the sampling algorithms, use ``pip install astartes`` (this install will have fewer dependencies and may be more readily compatible in environments with existing workflows). + +``conda`` +^^^^^^^^^^^^^ + +``astartes`` package is also available on ``conda-forge`` with this command: ``conda install -c conda-forge astartes``. +To install ``astartes`` with support for featurizing molecules, use: ``conda install -c conda-forge astartes aimsim``. +This will download the base ``astartes`` package as well as ``aimsim``\ , which is the backend used for molecular featurization. + +Source +^^^^^^ + +To install ``astartes`` from source for development, see the `Contributing & Developer Notes <#contributing--developer-notes>`_ section. + +Statement of Need +----------------- + +Machine learning has sparked an explosion of progress in chemical kinetics, materials science, and many other fields as researchers use data-driven methods to accelerate steps in traditional workflows within some acceptable error tolerance. +To facilitate adoption of these models, there are two important tasks to consider: + + +#. use a validation set when selecting the optimal hyperparameter for the model and separately use a held-out test set to measure performance on unseen data. +#. evaluate model performance on both interpolative and extrapolative tasks so future users are informed of any potential limitations. + +``astartes`` addresses both of these points by implementing an ``sklearn``\ -compatible ``train_val_test_split`` function. +Additional technical detail is provided below as well as in our companion `paper `_. +For a demo-based explainer using machine learning on a fast food menu, see the ``astartes`` Reproducible Notebook published at the United States Research Software Engineers Conference at `this page `_. + +Target Audience +^^^^^^^^^^^^^^^ + +``astartes`` is generally applicable to machine learning involving both discovery and inference *and* model validation. +There are specific functions in ``astartes`` for applications in cheminformatics (\ ``astartes.molecules``\ ) but the methods implemented are general to all numerical data. + +Quick Start +----------- + +``astartes`` is designed as a drop-in replacement for ``sklearn``\ 's ``train_test_split`` function (see the `sklearn documentation `_\ ). To switch to ``astartes``\ , change ``from sklearn.model_selection import train_test_split`` to ``from astartes import train_test_split``. + +Like ``sklearn``\ , ``astartes`` accepts any iterable object as ``X``\ , ``y``\ , and ``labels``. +Each will be converted to a ``numpy`` array for internal operations, and returned as a ``numpy`` array with limited exceptions: if ``X`` is a ``pandas`` ``DataFrame``\ , ``y`` is a ``Series``\ , or ``labels`` is a ``Series``\ , ``astartes`` will cast it back to its original type including its index and column names. + +.. + + **Note** + The developers recommend passing ``X``\ , ``y``\ , and ``labels`` as ``numpy`` arrays and handling the conversion to and from other types explicitly on your own. Behind-the-scenes type casting can lead to unexpected behavior! + + +By default, ``astartes`` will split data randomly. Additionally, a variety of algorithmic sampling approaches can be used by specifying the ``sampler`` argument to the function (see the `Table of Implemented Samplers <#implemented-sampling-algorithms>`_ for a complete list of options and their corresponding references): + +.. code-block:: python + + from sklearn.datasets import load_diabetes + + X, y = load_diabetes(return_X_y=True) + + X_train, X_test, y_train, y_test = train_test_split( + X, # preferably numpy arrays, but astartes will cast it for you + y, + sampler = 'kennard_stone', # any of the supported samplers + ) + +.. + + **Note** + Extrapolation sampling algorithms will return an additional set of arrays (the cluster labels) which will result in a ``ValueError: too many values to unpack`` if not called properly. See the `\ ``split_comparisons`` Google colab demo `_ for a full explanation. + + +That's all you need to get started with ``astartes``\ ! +The next sections include more examples and some demo notebooks you can try in your browser. + +Example Notebooks +^^^^^^^^^^^^^^^^^ + +Click the badges in the table below to be taken to a live, interactive demo of ``astartes``\ : + +.. list-table:: + :header-rows: 1 + + * - Demo + - Topic + - Link + * - Comparing Sampling Algorithms with Fast Food + - Visual representations of how different samplers affect data partitioning + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/split_comparisons/split_comparisons.ipynb + :alt: Colab + + * - Using ``train_val_test_split`` with the ``sklearn`` example datasets + - Demonstrating how witholding a test set with ``train_val_test_split`` can impact performance + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/train_val_test_split_sklearn_example/train_val_test_split_example.ipynb + :alt: Colab + + * - Cheminformatics sample set partitioning with ``astartes`` + - Extrapolation vs. Interpolation impact on cheminformatics model accuracy + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/barrier_prediction_with_RDB7/RDB7_barrier_prediction_example.ipynb + :alt: Colab + + * - Comparing partitioning approaches for alkanes + - Visualizing how sampler impact model performance with simple chemicals + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/mlpds_2023_astartes_demonstration/mlpds_2023_demo.ipynb + :alt: Colab + + + +To execute these notebooks locally, clone this repository (i.e. ``git clone https://github.com/JacksonBurns/astartes.git``\ ), navigate to the ``astartes`` directory, run ``pip install .[demos]``\ , then open and run the notebooks in your preferred editor. +You do *not* need to execute the cells prefixed with ``%%capture`` - they are only present for compatibility with Google Colab. + +Withhold Testing Data with ``train_val_test_split`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For rigorous ML research, it is critical to withhold some data during training to use a ``test`` set. +The model should *never* see this data during training (unlike the validation set) so that we can get an accurate measurement of its performance. + +With ``astartes`` performing this three-way data split is readily available with ``train_val_test_split``\ : + +.. code-block:: python + + from astartes import train_val_test_split + + X_train, X_val, X_test = train_val_test_split(X, sampler = 'sphere_exclusion') + +You can now train your model with ``X_train``\ , optimize your model with ``X_val``\ , and measure its performance with ``X_test``. + +Evaluate the Impact of Splitting Algorithms on Regression Models +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For data with many features it can be difficult to visualize how different sampling algorithms change the distribution of data into training, validation, and testing like we do in some of the demo notebooks. +To aid in analyzing the impact of the algorithms, ``astartes`` provides ``generate_regression_results_dict``. +This function allows users to quickly evaluate the impact of different splitting techniques on any ``sklearn``\ -compatible model's performance. +All results are stored in a nested dictionary (\ ``{sampler:{metric:{split:score}}}``\ ) format and can be displayed in a neatly formatted table using the optional ``print_results`` argument. + +.. code-block:: python + + from sklearn.svm import LinearSVR + + from astartes.utils import generate_regression_results_dict as grrd + + sklearn_model = LinearSVR() + results_dict = grrd( + sklearn_model, + X, + y, + print_results=True, + ) + + Train Val Test + ---- -------- -------- -------- + MAE 1.41522 3.13435 2.17091 + RMSE 2.03062 3.73721 2.40041 + R2 0.90745 0.80787 0.78412 + +Additional metrics can be passed to ``generate_regression_results_dict`` via the ``additional_metrics`` argument, which should be a dictionary mapping the name of the metric (as a ``string``\ ) to the function itself, like this: + +.. code-block:: python + + from sklearn.metrics import mean_absolute_percentage_error + + add_met = {"mape": mean_absolute_percentage_error} + + grrd(sklearn_model, X, y, additional_metric=add_met) + +See the docstring for ``generate_regression_results_dict`` (with ``help(generate_regression_results_dict)``\ ) for more information. + +Using ``astartes`` with Categorical Data +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Any of the implemented sampling algorithms whose hyperparameters allow specifying the ``metric`` or ``distance_metric`` (effectively ``1-metric``\ ) can be co-opted to work with categorical data. +Simply encode the data in a format compatible with the ``sklearn`` metric of choice and then call ``astartes`` with that metric specified: + +.. code-block:: python + + from sklearn.metrics import jaccard_score + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + sampler='kennard_stone', + hopts={"metric": jaccard_score}, + ) + +Other samplers which do not allow specifying a categorical distance metric did not provide a method for doing so in their original inception, though it is possible that they can be adapted for this application. +If you are interested in adding support for categorical metrics to an existing sampler, consider opening a `Feature Request `_\ ! + +Access Sampling Algorithms Directly +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The sampling algorithms implemented in ``astartes`` can also be directly accessed and run if it is more useful for your applications. +In the below example, we import the Kennard Stone sampler, use it to partition a simple array, and then retrieve a sample. + +.. code-block:: python + + from astartes.samplers.interpolation import KennardStone + + kennard_stone = KennardStone([[1, 2], [3, 4], [5, 6]]) + first_2_samples = kennard_stone.get_sample_idxs(2) + +All samplers in ``astartes`` implement a ``_sample()`` method that is called by the constructor (i.e. greedily) and either a ``get_sampler_idxs`` or ``get_cluster_idxs`` for interpolative and extrapolative samplers, respectively. +For more detail on the implementaiton and design of samplers in ``astartes``\ , see the `Developer Notes <#contributing--developer-notes>`_ section. + +Theory and Application of ``astartes`` +------------------------------------------ + +This section of the README details some of the theory behind why the algorithms implemented in ``astartes`` are important and some motivating examples. +For a comprehensive walkthrough of the theory and implementation of ``astartes``\ , follow `this link `_ to read the companion paper (freely available and hosted here on GitHub). + +.. + + **Note** + We reference open-access publications wherever possible. For articles locked behind a paywall (denoted with :small_blue_diamond:), we instead suggest reading `this Wikipedia page `_ and absolutely **not** attempting to bypass the paywall. + + +Rational Splitting Algorithms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While much machine learning is done with a random choice between training/validation/test data, an alternative is the use of so-called "rational" splitting algorithms. +These approaches use some similarity-based algorithm to divide data into sets. +Some of these algorithms include Kennard-Stone (\ `Kennard & Stone `_ :small_blue_diamond:), Sphere Exclusion (\ `Tropsha et. al `_ :small_blue_diamond:),as well as the OptiSim as discussed in `Applied Chemoinformatics: Achievements and Future Opportunities `_ :small_blue_diamond:. +Some clustering-based splitting techniques have also been incorporated, such as `DBSCAN `_. + +There are two broad categories of sampling algorithms implemented in ``astartes``\ : extrapolative and interpolative. +The former will force your model to predict on out-of-sample data, which creates a more challenging task than interpolative sampling. +See the table below for all of the sampling approaches currently implemented in ``astartes``\ , as well as the hyperparameters that each algorithm accepts (which are passed in with ``hopts``\ ) and a helpful reference for understanding how the hyperparameters work. +Note that ``random_state`` is defined as a keyword argument in ``train_test_split`` itself, even though these algorithms will use the ``random_state`` in their own work. +Do not provide a ``random_state`` in the ``hopts`` dictionary - it will be overwritten by the ``random_state`` you provide for ``train_test_split`` (or the default if none is provided). + +Implemented Sampling Algorithms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - Sampler Name + - Usage String + - Type + - Hyperparameters + - Reference + - Notes + * - Random + - 'random' + - Interpolative + - ``shuffle`` + - `sklearn train_test_split `_ Documentation + - This sampler is a direct passthrough to ``sklearn``\ 's ``train_test_split``. + * - Kennard-Stone + - 'kennard_stone' + - Interpolative + - ``metric`` + - Original Paper by `Kennard & Stone `_ :small_blue_diamond: + - Euclidian distance is used by default, as described in the original paper. + * - Sample set Partitioning based on joint X-Y distances (SPXY) + - 'spxy' + - Interpolative + - ``distance_metric`` + - Saldhana et. al `original paper `_ :small_blue_diamond: + - Extension of Kennard Stone that also includes the response when sampling distances. + * - Mahalanobis Distance Kennard Stone (MDKS) + - 'spxy' *(MDKS is derived from SPXY)* + - Interpolative + - *none, see Notes* + - Saptoro et. al `original paper `_ + - MDKS is SPXY using Mahalanobis distance and can be called by using SPXY with ``distance_metric="mahalanobis"`` + * - Scaffold + - 'scaffold' + - Extrapolative + - ``include_chirality`` + - `Bemis-Murcko Scaffold `_ :small_blue_diamond: as implemented in RDKit + - This sampler requires SMILES strings as input (use the ``molecules`` subpackage) + * - Sphere Exclusion + - 'sphere_exclusion' + - Extrapolative + - ``metric``\ , ``distance_cutoff`` + - *custom implementation* + - Variation on Sphere Exclusion for arbitrary-valued vectors. + * - Time Based + - 'time_based' + - Extrapolative + - *none* + - Papers using Time based splitting: `Chen et al. `_ :small_blue_diamond:, `Sheridan, R. P `_ :small_blue_diamond:, `Feinberg et al. `_ :small_blue_diamond:, `Struble et al. `_ + - This sampler requires ``labels`` to be an iterable of either date or datetime objects. + * - Optimizable K-Dissimilarity Selection (OptiSim) + - 'optisim' + - Extrapolative + - ``n_clusters``\ , ``max_subsample_size``\ , ``distance_cutoff`` + - *custom implementation* + - Variation on `OptiSim `_ for arbitrary-valued vectors. + * - K-Means + - 'kmeans' + - Extrapolative + - ``n_clusters``\ , ``n_init`` + - `\ ``sklearn KMeans`` `_ + - Passthrough to ``sklearn``\ 's ``KMeans``. + * - Density-Based Spatial Clustering of Applications with Noise (DBSCAN) + - 'dbscan' + - Extrapolative + - ``eps``\ , ``min_samples``\ , ``algorithm``\ , ``metric``\ , ``leaf_size`` + - `\ ``sklearn DBSCAN`` `_ Documentation + - Passthrough to ``sklearn``\ 's ``DBSCAN``. + * - Minimum Test Set Dissimilarity (MTSD) + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + * - Restricted Boltzmann Machine (RBM) + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + * - Kohonen Self-Organizing Map (SOM) + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + * - SPlit Method + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + + +Domain-Specific Applications +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Below are some field specific applications of ``astartes``. Interested in adding a new sampling algorithm or featurization approach? See `\ ``CONTRIBUTING.md`` <./CONTRIBUTING.md>`_. + +Chemical Data and the ``astartes.molecules`` Subpackage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Machine Learning is enormously useful in chemistry-related fields due to the high-dimensional feature space of chemical data. +To properly apply ML to chemical data for inference *or* discovery, it is important to know a model's accuracy under the two domains. +To simplify the process of partitioning chemical data, ``astartes`` implements a pre-built featurizer for common chemistry data formats. +After installing with ``pip install astartes[molecules]`` one can import the new train/test splitting function like this: ``from astartes.molecules import train_test_split_molecules`` + +The usage of this function is identical to ``train_test_split`` but with the addition of new arguments to control how the molecules are featurized: + +.. code-block:: python + + train_test_split_molecules( + molecules=smiles, + y=y, + test_size=0.2, + train_size=0.8, + fingerprint="daylight_fingerprint", + fprints_hopts={ + "minPath": 2, + "maxPath": 5, + "fpSize": 200, + "bitsPerHash": 4, + "useHs": 1, + "tgtDensity": 0.4, + "minSize": 64, + }, + sampler="random", + random_state=42, + hopts={ + "shuffle": True, + }, + ) + +To see a complete example of using ``train_test_split_molecules`` with actual chemical data, take a look in the ``examples`` directory and the brief `companion paper `_. + +Configuration options for the featurization scheme can be found in the documentation for `AIMSim `_ though most of the critical configuration options are shown above. + +Reproducibility +--------------- + +``astartes`` aims to be completely reproducible across different platforms, Python versions, and dependency configurations - any version of ``astartes`` v1.x should result in the *exact* same splits, always. +To that end, the default behavior of ``astartes`` is to use ``42`` as the random seed and *always* set it. +Running ``astartes`` with the default settings will always produce the exact same results. +We have verified this behavior on Debian Ubuntu, Windows, and Intel Macs from Python versions 3.7 through 3.11 (with appropriate dependencies for each version). + +Known Reproducibility Limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Inevitably external dependencies of ``astartes`` will introduce backwards-incompatible changes. +We continually run regression tests to catch these, and will list all *known* limitations here: + + +* ``sklearn`` v1.3.0 introduced backwards-incompatible changes in the ``KMeans`` sampler that changed how the random initialization affects the results, even given the same random seed. Different version of ``sklearn`` will affect the performance of ``astartes`` and we recommend including the exact version of ``scikit-learn`` and ``astartes`` used, when applicable. + +.. + + **Note** + We are limited in our ability to test on M1 Macs, but from our limited manual testing we achieve perfect reproducbility in all cases *except occasionally* with ``KMeans`` on Apple silicon. + ``astartes`` is still consistent between runs on the same platform in all cases, and other samplers are not impacted by this apparent bug. + + +How to Cite +----------- + +If you use ``astartes`` in your work please use the below citation or the "Cite this repository" button on GitHub: + +.. + + **BibTeX** + @software{burns_jackson_2023_8147205, + author = {Burns, Jackson and + Spiekermann, Kevin and + Bhattacharjee, Himaghna and + Vlachos, Dionisios and + Green, William}, + title = {{Machine Learning Validation via Rational Dataset + Sampling with astartes}}, + month = may, + year = 2023, + publisher = {Zenodo}, + version = {1.1.1}, + doi = {10.5281/zenodo.8147205}, + url = {https://doi.org/10.5281/zenodo.8147205} + } + + +Contributing & Developer Notes +------------------------------ + +See `CONTRIBUTING.md <./CONTRIBUTING.md>`_ for instructions on installing ``astartes`` for development, making a contribution, and general guidance on the design of ``astartes``. diff --git a/docs/_sources/CONTRIBUTING.rst.txt b/docs/_sources/CONTRIBUTING.rst.txt new file mode 100644 index 00000000..677944a2 --- /dev/null +++ b/docs/_sources/CONTRIBUTING.rst.txt @@ -0,0 +1,143 @@ + +Contributing & Developer Notes +------------------------------ + +Pull Requests, Bug Reports, and all Contributions are welcome, encouraged, and appreciated! +Please use the appropriate `issue `_ or `pull request `_ template when making a contribution to help the maintainers get it merged quickly. + +We make use of `the GitHub Discussions page `_ to go over potential features to add. +Please feel free to stop by if you are looking for something to develop or have an idea for a useful feature! + +When submitting a PR, please mark your PR with the "PR Ready for Review" label when you are finished making changes so that the GitHub actions bots can work their magic! + +Developer Install +^^^^^^^^^^^^^^^^^ + +To contribute to the ``astartes`` source code, start by forking and then cloning the repository (i.e. ``git clone git@github.com:YourUsername/astartes.git``\ ) and then inside the repository run ``pip install -e .[dev]``. This will set you up with all the required dependencies to run ``astartes`` and conform to our formatting standards (\ ``black`` and ``isort``\ ), which you can configure to run automatically in VSCode `like this `_. + +.. + + **Warning** + Windows (PowerShell) and MacOS Catalina or newer (zsh) require double quotes around the ``[]`` characters (i.e. ``pip install "astartes[dev]"``\ ) + + +Version Checking +^^^^^^^^^^^^^^^^ + +``astartes`` uses ``pyproject.toml`` to specify all metadata, but the version is also specified in ``astartes/__init__.py`` (via ``__version__``\ ) for backwards compatibility with Python 3.7. +To check which version of ``astartes`` you have installed, you can run ``python -c "import astartes; print(astartes.__version__)"`` on Python 3.7 or `python -c "from importlib.metadata import version; version('astartes')" on Python 3.8 or newer. + +Testing +^^^^^^^ + +All of the tests in ``astartes`` are written using the built-in python ``unittest`` module (to allow running without ``pytest``\ ) but we *highly* recommend using ``pytest``. +To execute the tests from the ``astartes`` repository, simply type ``pytest`` after running the developer install (or alternately, ``pytest -v`` for a more helpful output). +On GitHub, we use actions to run the tests on every Pull Request and on a nightly basis (look in ``.github/workflows`` for more information). +These tests include unit tests, functional tests, and regression tests. + +Adding New Samplers +^^^^^^^^^^^^^^^^^^^ + +Adding a new sampler should extend the ``abstract_sampler.py`` abstract base class. +Each subclass should override the ``_sample`` method with its own algorithm for data partitioning and optionally the ``_before_sample`` method to perform any data validation. + +All samplers in ``astartes`` are classified as one of two types: extrapolative or interpolative. +Extrapolative samplers work by clustering data into groups (which are then partitioned into train/validation/test to enforce extrapolation) whereas interpolative samplers provide an exact *order* in which samples should be moved into the training set. + +When actually implemented, this means that extrapolative samplers should set the ``self._samples_clusters`` attribute and interpolative samplers should set the ``self._samples_idxs`` attribute. + +New samplers can be as simple as a passthrough to another ``train_test_split``\ , or it can be an original implementation that results in X and y being split into two lists. Take a look at ``astartes/samplers/interpolation/random_split.py`` for a basic example! + +After the sampler has been implemented, add it to ``__init__.py`` in in ``astartes/samplers`` and it will automatically be unit tested. Additional unit tests to verify that hyperparameters can be properly passed, etc. are also recommended. + +For historical reasons, and as a guide for any developers who would like add new samplers, below is a running list of samplers which have been *considered* for addition to ``asartes`` but ultimately not added for various reasons. + +Not Implemented Sampling Algorithms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - Sampler Name + - Reasoning + - Relevant Link(s) + * - D-Optimal + - Requires *a-priori* knowledge of the test and train size which does not fit in the ``astartes`` framework (samplers are all agnostic to the size of the sets) and it is questionable if the use of the Fischer information matrix is actually meaningful in the context of sampling existing data rather than tuning for ideal data. + - The `Wikipedia article for optimal design `_ does a good job explaining why this is difficult, and points at some potential alternatives. + * - Duplex + - Requires knowing test and train size before execution, and can only partition data into two sets which would make it incompatible with ``train_val_test_split``. + - This `implementation in R `_ includes helpful references and a reference implementation. + + +Adding New Featurization Schemes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All of the sampling methods implemented in ``astartes`` accept arbitrary arrays of numbers and return the sampled groups (with the exception of ``Scaffold.py``\ ). If you have an existing featurization scheme (i.e. take an arbitrary input and turn it into an array of numbers), we would be thrilled to include it in ``astartes``. + +Adding a new interface should take on this format: + +.. code-block:: python + + from astartes import train_test_split + + def train_test_split_INTERFACE( + INTERFACE_input, + INTERFACE_ARGS, + y: np.array = None, + labels: np.array = None, + test_size: float = 0.25, + train_size: float = 0.75, + splitter: str = 'random', + hopts: dict = {}, + INTERFACE_hopts: dict = {}, + ): + # turn the INTERFACE_input into an input X + # based on INTERFACE ARGS where INTERFACE_hopts + # specifies additional behavior + X = [] + + # call train test split with this input + return train_test_split( + X, + y=y, + labels=labels, + test_size=test_size, + train_size=train_size, + splitter=splitter, + hopts=hopts, + ) + +If possible, we would like to also add an example Jupyter Notebook with any new interface to demonstrate to new users how it functions. See our other examples in the ``examples`` directory. + +Contact `@JacksonBurns `_ if you need assistance adding an existing workflow to ``astartes``. If this featurization scheme requires additional dependencies to function, we may add it as an additional *extra* package in the same way that ``molecules`` in installed. + +The ``train_val_test_split`` Function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``train_val_test_split`` is the workhorse function of ``astartes``. +It is responsible for instantiating the sampling algorithm, partitioning the data into training, validation, and testing, and then returning the requested results while also keeping an eye on data types. +Under the hood, ``train_test_split`` is just calling ``train_val_test_split`` with ``val_size`` set to ``0.0``. +For more information on how it works, check out the inline documentation in ``astartes/main.py``. + +Development Philosophy +^^^^^^^^^^^^^^^^^^^^^^ + +The developers of ``astartes`` prioritize (1) reproducibility, (2) flexibility, and (3) maintainability. + + +#. All versions of ``astartes`` ``1.x`` should produce the same results across all platforms, so we have thorough unit and regression testing run on a continuous basis. +#. We specify as *few dependencies as possible* with the *loosest possible* dependency requirements, which allows integrating ``astartes`` with other tools more easily. + + * Dependencies which introduce a lot of requirements and/or specific versions of requirements are shuffled into the ``extras_require`` to avoid weighing down the main package. + * Compatibility with all versions of modern Python is achieved by not tightly specifying version numbers as well as by regression testing across all versions. + +#. We follow DRY (Don't Repeat Yourself) principles to avoid code duplication and decrease maintainence burden, have near-perfect test coverage, and enforce consistent formatting style in the source code. + + * Inline comments are *critical* for maintainability - at the time of writing, ``astartes`` has 1 comment line for every 2 lines of source code. + +JOSS Branch +----------- + +``astartes`` corresponding JOSS paper is stored in this repository on a separate branch. You can find ``paper.md`` on the aptly named ``joss-paper`` branch. + +*Note for Maintainers*\ : To push changes from the ``main`` branch into the ``joss-paper`` branch, run the ``Update JOSS Branch`` workflow. diff --git a/docs/_sources/README.rst.txt b/docs/_sources/README.rst.txt new file mode 100644 index 00000000..0baa5f3c --- /dev/null +++ b/docs/_sources/README.rst.txt @@ -0,0 +1,504 @@ +.. role:: raw-html-m2r(raw) + :format: html + + +:raw-html-m2r:`

astartes

` + +:raw-html-m2r:`

(as-tar-tees)

` + + +.. raw:: html + +

Train:Validation:Test Algorithmic Sampling for Molecules and Arbitrary Arrays

+ + +:raw-html-m2r:`

+ astarteslogo +

` + + +.. raw:: html + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Status Badges

UsageContinuous IntegrationRelease
PyPI - Python VersionReproduce PaperpyOpenSci approved
PyPI - LicenseTest StatusDOI
PyPI - Total DownloadsPyPI conda-forge version
GitHub Repo StarsProject Status: Active – The project has reached a stable, usable state and is being actively developed.
+
+ + +Online Documentation +-------------------- + +Follow `this link `_ for a nicely-rendered version of this README along with additional tutorials for `moving from train_test_split in sklearn to astartes `_. +Keep reading for a installation guide and links to tutorials! + +Installing ``astartes`` +--------------------------- + +We recommend installing ``astartes`` within a virtual environment, using either ``venv`` or ``conda`` (or other tools) to simplify dependency management. Python versions 3.7, 3.8, 3.9, 3.10, and 3.11 are supported on all platforms. + +.. + + **Warning** + Windows (PowerShell) and MacOS Catalina or newer (zsh) require double quotes around text using the ``'[]'`` characters (i.e. ``pip install "astartes[molecules]"``\ ). + + +``pip`` +^^^^^^^^^^^ + +``astartes`` is available on ``PyPI`` and can be installed using ``pip``\ : + + +* To include the featurization options for chemical data, use ``pip install astartes[molecules]``. +* To install only the sampling algorithms, use ``pip install astartes`` (this install will have fewer dependencies and may be more readily compatible in environments with existing workflows). + +``conda`` +^^^^^^^^^^^^^ + +``astartes`` package is also available on ``conda-forge`` with this command: ``conda install -c conda-forge astartes``. +To install ``astartes`` with support for featurizing molecules, use: ``conda install -c conda-forge astartes aimsim``. +This will download the base ``astartes`` package as well as ``aimsim``\ , which is the backend used for molecular featurization. + +Source +^^^^^^ + +To install ``astartes`` from source for development, see the `Contributing & Developer Notes <#contributing--developer-notes>`_ section. + +Statement of Need +----------------- + +Machine learning has sparked an explosion of progress in chemical kinetics, materials science, and many other fields as researchers use data-driven methods to accelerate steps in traditional workflows within some acceptable error tolerance. +To facilitate adoption of these models, there are two important tasks to consider: + + +#. use a validation set when selecting the optimal hyperparameter for the model and separately use a held-out test set to measure performance on unseen data. +#. evaluate model performance on both interpolative and extrapolative tasks so future users are informed of any potential limitations. + +``astartes`` addresses both of these points by implementing an ``sklearn``\ -compatible ``train_val_test_split`` function. +Additional technical detail is provided below as well as in our companion `paper `_. +For a demo-based explainer using machine learning on a fast food menu, see the ``astartes`` Reproducible Notebook published at the United States Research Software Engineers Conference at `this page `_. + +Target Audience +^^^^^^^^^^^^^^^ + +``astartes`` is generally applicable to machine learning involving both discovery and inference *and* model validation. +There are specific functions in ``astartes`` for applications in cheminformatics (\ ``astartes.molecules``\ ) but the methods implemented are general to all numerical data. + +Quick Start +----------- + +``astartes`` is designed as a drop-in replacement for ``sklearn``\ 's ``train_test_split`` function (see the `sklearn documentation `_\ ). To switch to ``astartes``\ , change ``from sklearn.model_selection import train_test_split`` to ``from astartes import train_test_split``. + +Like ``sklearn``\ , ``astartes`` accepts any iterable object as ``X``\ , ``y``\ , and ``labels``. +Each will be converted to a ``numpy`` array for internal operations, and returned as a ``numpy`` array with limited exceptions: if ``X`` is a ``pandas`` ``DataFrame``\ , ``y`` is a ``Series``\ , or ``labels`` is a ``Series``\ , ``astartes`` will cast it back to its original type including its index and column names. + +.. + + **Note** + The developers recommend passing ``X``\ , ``y``\ , and ``labels`` as ``numpy`` arrays and handling the conversion to and from other types explicitly on your own. Behind-the-scenes type casting can lead to unexpected behavior! + + +By default, ``astartes`` will split data randomly. Additionally, a variety of algorithmic sampling approaches can be used by specifying the ``sampler`` argument to the function (see the `Table of Implemented Samplers <#implemented-sampling-algorithms>`_ for a complete list of options and their corresponding references): + +.. code-block:: python + + from sklearn.datasets import load_diabetes + + X, y = load_diabetes(return_X_y=True) + + X_train, X_test, y_train, y_test = train_test_split( + X, # preferably numpy arrays, but astartes will cast it for you + y, + sampler = 'kennard_stone', # any of the supported samplers + ) + +.. + + **Note** + Extrapolation sampling algorithms will return an additional set of arrays (the cluster labels) which will result in a ``ValueError: too many values to unpack`` if not called properly. See the `\ ``split_comparisons`` Google colab demo `_ for a full explanation. + + +That's all you need to get started with ``astartes``\ ! +The next sections include more examples and some demo notebooks you can try in your browser. + +Example Notebooks +^^^^^^^^^^^^^^^^^ + +Click the badges in the table below to be taken to a live, interactive demo of ``astartes``\ : + +.. list-table:: + :header-rows: 1 + + * - Demo + - Topic + - Link + * - Comparing Sampling Algorithms with Fast Food + - Visual representations of how different samplers affect data partitioning + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/split_comparisons/split_comparisons.ipynb + :alt: Colab + + * - Using ``train_val_test_split`` with the ``sklearn`` example datasets + - Demonstrating how witholding a test set with ``train_val_test_split`` can impact performance + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/train_val_test_split_sklearn_example/train_val_test_split_example.ipynb + :alt: Colab + + * - Cheminformatics sample set partitioning with ``astartes`` + - Extrapolation vs. Interpolation impact on cheminformatics model accuracy + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/barrier_prediction_with_RDB7/RDB7_barrier_prediction_example.ipynb + :alt: Colab + + * - Comparing partitioning approaches for alkanes + - Visualizing how sampler impact model performance with simple chemicals + - + .. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/JacksonBurns/astartes/blob/main/examples/mlpds_2023_astartes_demonstration/mlpds_2023_demo.ipynb + :alt: Colab + + + +To execute these notebooks locally, clone this repository (i.e. ``git clone https://github.com/JacksonBurns/astartes.git``\ ), navigate to the ``astartes`` directory, run ``pip install .[demos]``\ , then open and run the notebooks in your preferred editor. +You do *not* need to execute the cells prefixed with ``%%capture`` - they are only present for compatibility with Google Colab. + +Withhold Testing Data with ``train_val_test_split`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For rigorous ML research, it is critical to withhold some data during training to use a ``test`` set. +The model should *never* see this data during training (unlike the validation set) so that we can get an accurate measurement of its performance. + +With ``astartes`` performing this three-way data split is readily available with ``train_val_test_split``\ : + +.. code-block:: python + + from astartes import train_val_test_split + + X_train, X_val, X_test = train_val_test_split(X, sampler = 'sphere_exclusion') + +You can now train your model with ``X_train``\ , optimize your model with ``X_val``\ , and measure its performance with ``X_test``. + +Evaluate the Impact of Splitting Algorithms on Regression Models +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For data with many features it can be difficult to visualize how different sampling algorithms change the distribution of data into training, validation, and testing like we do in some of the demo notebooks. +To aid in analyzing the impact of the algorithms, ``astartes`` provides ``generate_regression_results_dict``. +This function allows users to quickly evaluate the impact of different splitting techniques on any ``sklearn``\ -compatible model's performance. +All results are stored in a nested dictionary (\ ``{sampler:{metric:{split:score}}}``\ ) format and can be displayed in a neatly formatted table using the optional ``print_results`` argument. + +.. code-block:: python + + from sklearn.svm import LinearSVR + + from astartes.utils import generate_regression_results_dict as grrd + + sklearn_model = LinearSVR() + results_dict = grrd( + sklearn_model, + X, + y, + print_results=True, + ) + + Train Val Test + ---- -------- -------- -------- + MAE 1.41522 3.13435 2.17091 + RMSE 2.03062 3.73721 2.40041 + R2 0.90745 0.80787 0.78412 + +Additional metrics can be passed to ``generate_regression_results_dict`` via the ``additional_metrics`` argument, which should be a dictionary mapping the name of the metric (as a ``string``\ ) to the function itself, like this: + +.. code-block:: python + + from sklearn.metrics import mean_absolute_percentage_error + + add_met = {"mape": mean_absolute_percentage_error} + + grrd(sklearn_model, X, y, additional_metric=add_met) + +See the docstring for ``generate_regression_results_dict`` (with ``help(generate_regression_results_dict)``\ ) for more information. + +Using ``astartes`` with Categorical Data +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Any of the implemented sampling algorithms whose hyperparameters allow specifying the ``metric`` or ``distance_metric`` (effectively ``1-metric``\ ) can be co-opted to work with categorical data. +Simply encode the data in a format compatible with the ``sklearn`` metric of choice and then call ``astartes`` with that metric specified: + +.. code-block:: python + + from sklearn.metrics import jaccard_score + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + sampler='kennard_stone', + hopts={"metric": jaccard_score}, + ) + +Other samplers which do not allow specifying a categorical distance metric did not provide a method for doing so in their original inception, though it is possible that they can be adapted for this application. +If you are interested in adding support for categorical metrics to an existing sampler, consider opening a `Feature Request `_\ ! + +Access Sampling Algorithms Directly +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The sampling algorithms implemented in ``astartes`` can also be directly accessed and run if it is more useful for your applications. +In the below example, we import the Kennard Stone sampler, use it to partition a simple array, and then retrieve a sample. + +.. code-block:: python + + from astartes.samplers.interpolation import KennardStone + + kennard_stone = KennardStone([[1, 2], [3, 4], [5, 6]]) + first_2_samples = kennard_stone.get_sample_idxs(2) + +All samplers in ``astartes`` implement a ``_sample()`` method that is called by the constructor (i.e. greedily) and either a ``get_sampler_idxs`` or ``get_cluster_idxs`` for interpolative and extrapolative samplers, respectively. +For more detail on the implementaiton and design of samplers in ``astartes``\ , see the `Developer Notes <#contributing--developer-notes>`_ section. + +Theory and Application of ``astartes`` +------------------------------------------ + +This section of the README details some of the theory behind why the algorithms implemented in ``astartes`` are important and some motivating examples. +For a comprehensive walkthrough of the theory and implementation of ``astartes``\ , follow `this link `_ to read the companion paper (freely available and hosted here on GitHub). + +.. + + **Note** + We reference open-access publications wherever possible. For articles locked behind a paywall (denoted with :small_blue_diamond:), we instead suggest reading `this Wikipedia page `_ and absolutely **not** attempting to bypass the paywall. + + +Rational Splitting Algorithms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While much machine learning is done with a random choice between training/validation/test data, an alternative is the use of so-called "rational" splitting algorithms. +These approaches use some similarity-based algorithm to divide data into sets. +Some of these algorithms include Kennard-Stone (\ `Kennard & Stone `_ :small_blue_diamond:), Sphere Exclusion (\ `Tropsha et. al `_ :small_blue_diamond:),as well as the OptiSim as discussed in `Applied Chemoinformatics: Achievements and Future Opportunities `_ :small_blue_diamond:. +Some clustering-based splitting techniques have also been incorporated, such as `DBSCAN `_. + +There are two broad categories of sampling algorithms implemented in ``astartes``\ : extrapolative and interpolative. +The former will force your model to predict on out-of-sample data, which creates a more challenging task than interpolative sampling. +See the table below for all of the sampling approaches currently implemented in ``astartes``\ , as well as the hyperparameters that each algorithm accepts (which are passed in with ``hopts``\ ) and a helpful reference for understanding how the hyperparameters work. +Note that ``random_state`` is defined as a keyword argument in ``train_test_split`` itself, even though these algorithms will use the ``random_state`` in their own work. +Do not provide a ``random_state`` in the ``hopts`` dictionary - it will be overwritten by the ``random_state`` you provide for ``train_test_split`` (or the default if none is provided). + +Implemented Sampling Algorithms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + + * - Sampler Name + - Usage String + - Type + - Hyperparameters + - Reference + - Notes + * - Random + - 'random' + - Interpolative + - ``shuffle`` + - `sklearn train_test_split `_ Documentation + - This sampler is a direct passthrough to ``sklearn``\ 's ``train_test_split``. + * - Kennard-Stone + - 'kennard_stone' + - Interpolative + - ``metric`` + - Original Paper by `Kennard & Stone `_ :small_blue_diamond: + - Euclidian distance is used by default, as described in the original paper. + * - Sample set Partitioning based on joint X-Y distances (SPXY) + - 'spxy' + - Interpolative + - ``distance_metric`` + - Saldhana et. al `original paper `_ :small_blue_diamond: + - Extension of Kennard Stone that also includes the response when sampling distances. + * - Mahalanobis Distance Kennard Stone (MDKS) + - 'spxy' *(MDKS is derived from SPXY)* + - Interpolative + - *none, see Notes* + - Saptoro et. al `original paper `_ + - MDKS is SPXY using Mahalanobis distance and can be called by using SPXY with ``distance_metric="mahalanobis"`` + * - Scaffold + - 'scaffold' + - Extrapolative + - ``include_chirality`` + - `Bemis-Murcko Scaffold `_ :small_blue_diamond: as implemented in RDKit + - This sampler requires SMILES strings as input (use the ``molecules`` subpackage) + * - Sphere Exclusion + - 'sphere_exclusion' + - Extrapolative + - ``metric``\ , ``distance_cutoff`` + - *custom implementation* + - Variation on Sphere Exclusion for arbitrary-valued vectors. + * - Time Based + - 'time_based' + - Extrapolative + - *none* + - Papers using Time based splitting: `Chen et al. `_ :small_blue_diamond:, `Sheridan, R. P `_ :small_blue_diamond:, `Feinberg et al. `_ :small_blue_diamond:, `Struble et al. `_ + - This sampler requires ``labels`` to be an iterable of either date or datetime objects. + * - Optimizable K-Dissimilarity Selection (OptiSim) + - 'optisim' + - Extrapolative + - ``n_clusters``\ , ``max_subsample_size``\ , ``distance_cutoff`` + - *custom implementation* + - Variation on `OptiSim `_ for arbitrary-valued vectors. + * - K-Means + - 'kmeans' + - Extrapolative + - ``n_clusters``\ , ``n_init`` + - `\ ``sklearn KMeans`` `_ + - Passthrough to ``sklearn``\ 's ``KMeans``. + * - Density-Based Spatial Clustering of Applications with Noise (DBSCAN) + - 'dbscan' + - Extrapolative + - ``eps``\ , ``min_samples``\ , ``algorithm``\ , ``metric``\ , ``leaf_size`` + - `\ ``sklearn DBSCAN`` `_ Documentation + - Passthrough to ``sklearn``\ 's ``DBSCAN``. + * - Minimum Test Set Dissimilarity (MTSD) + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + * - Restricted Boltzmann Machine (RBM) + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + * - Kohonen Self-Organizing Map (SOM) + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + * - SPlit Method + - ~ + - ~ + - *upcoming in* ``astartes`` *v1.x* + - ~ + - ~ + + +Domain-Specific Applications +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Below are some field specific applications of ``astartes``. Interested in adding a new sampling algorithm or featurization approach? See `\ ``CONTRIBUTING.md`` <./CONTRIBUTING.md>`_. + +Chemical Data and the ``astartes.molecules`` Subpackage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Machine Learning is enormously useful in chemistry-related fields due to the high-dimensional feature space of chemical data. +To properly apply ML to chemical data for inference *or* discovery, it is important to know a model's accuracy under the two domains. +To simplify the process of partitioning chemical data, ``astartes`` implements a pre-built featurizer for common chemistry data formats. +After installing with ``pip install astartes[molecules]`` one can import the new train/test splitting function like this: ``from astartes.molecules import train_test_split_molecules`` + +The usage of this function is identical to ``train_test_split`` but with the addition of new arguments to control how the molecules are featurized: + +.. code-block:: python + + train_test_split_molecules( + molecules=smiles, + y=y, + test_size=0.2, + train_size=0.8, + fingerprint="daylight_fingerprint", + fprints_hopts={ + "minPath": 2, + "maxPath": 5, + "fpSize": 200, + "bitsPerHash": 4, + "useHs": 1, + "tgtDensity": 0.4, + "minSize": 64, + }, + sampler="random", + random_state=42, + hopts={ + "shuffle": True, + }, + ) + +To see a complete example of using ``train_test_split_molecules`` with actual chemical data, take a look in the ``examples`` directory and the brief `companion paper `_. + +Configuration options for the featurization scheme can be found in the documentation for `AIMSim `_ though most of the critical configuration options are shown above. + +Reproducibility +--------------- + +``astartes`` aims to be completely reproducible across different platforms, Python versions, and dependency configurations - any version of ``astartes`` v1.x should result in the *exact* same splits, always. +To that end, the default behavior of ``astartes`` is to use ``42`` as the random seed and *always* set it. +Running ``astartes`` with the default settings will always produce the exact same results. +We have verified this behavior on Debian Ubuntu, Windows, and Intel Macs from Python versions 3.7 through 3.11 (with appropriate dependencies for each version). + +Known Reproducibility Limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Inevitably external dependencies of ``astartes`` will introduce backwards-incompatible changes. +We continually run regression tests to catch these, and will list all *known* limitations here: + + +* ``sklearn`` v1.3.0 introduced backwards-incompatible changes in the ``KMeans`` sampler that changed how the random initialization affects the results, even given the same random seed. Different version of ``sklearn`` will affect the performance of ``astartes`` and we recommend including the exact version of ``scikit-learn`` and ``astartes`` used, when applicable. + +.. + + **Note** + We are limited in our ability to test on M1 Macs, but from our limited manual testing we achieve perfect reproducbility in all cases *except occasionally* with ``KMeans`` on Apple silicon. + ``astartes`` is still consistent between runs on the same platform in all cases, and other samplers are not impacted by this apparent bug. + + +How to Cite +----------- + +If you use ``astartes`` in your work please use the below citation or the "Cite this repository" button on GitHub: + +.. + + **BibTeX** + @software{burns_jackson_2023_8147205, + author = {Burns, Jackson and + Spiekermann, Kevin and + Bhattacharjee, Himaghna and + Vlachos, Dionisios and + Green, William}, + title = {{Machine Learning Validation via Rational Dataset + Sampling with astartes}}, + month = may, + year = 2023, + publisher = {Zenodo}, + version = {1.1.1}, + doi = {10.5281/zenodo.8147205}, + url = {https://doi.org/10.5281/zenodo.8147205} + } + + +Contributing & Developer Notes +------------------------------ + +See `CONTRIBUTING.md <./CONTRIBUTING.md>`_ for instructions on installing ``astartes`` for development, making a contribution, and general guidance on the design of ``astartes``. diff --git a/docs/_sources/astartes.rst.txt b/docs/_sources/astartes.rst.txt index 2d827941..4af4818c 100644 --- a/docs/_sources/astartes.rst.txt +++ b/docs/_sources/astartes.rst.txt @@ -7,16 +7,24 @@ Subpackages .. toctree:: :maxdepth: 4 - astartes.interfaces astartes.samplers + astartes.utils Submodules ---------- -astartes.astartes module ------------------------- +astartes.main module +-------------------- -.. automodule:: astartes.astartes +.. automodule:: astartes.main + :members: + :undoc-members: + :show-inheritance: + +astartes.molecules module +------------------------- + +.. automodule:: astartes.molecules :members: :undoc-members: :show-inheritance: diff --git a/docs/_sources/astartes.samplers.extrapolation.rst.txt b/docs/_sources/astartes.samplers.extrapolation.rst.txt new file mode 100644 index 00000000..6fd2f0b8 --- /dev/null +++ b/docs/_sources/astartes.samplers.extrapolation.rst.txt @@ -0,0 +1,61 @@ +astartes.samplers.extrapolation package +======================================= + +Submodules +---------- + +astartes.samplers.extrapolation.dbscan module +--------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.dbscan + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.kmeans module +--------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.kmeans + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.optisim module +---------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.optisim + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.scaffold module +----------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.scaffold + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.sphere\_exclusion module +-------------------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.sphere_exclusion + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.time\_based module +-------------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.time_based + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes.samplers.extrapolation + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/astartes.samplers.interpolation.rst.txt b/docs/_sources/astartes.samplers.interpolation.rst.txt new file mode 100644 index 00000000..91f887d4 --- /dev/null +++ b/docs/_sources/astartes.samplers.interpolation.rst.txt @@ -0,0 +1,37 @@ +astartes.samplers.interpolation package +======================================= + +Submodules +---------- + +astartes.samplers.interpolation.kennardstone module +--------------------------------------------------- + +.. automodule:: astartes.samplers.interpolation.kennardstone + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.interpolation.random\_split module +---------------------------------------------------- + +.. automodule:: astartes.samplers.interpolation.random_split + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.interpolation.spxy module +------------------------------------------- + +.. automodule:: astartes.samplers.interpolation.spxy + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes.samplers.interpolation + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/astartes.samplers.rst.txt b/docs/_sources/astartes.samplers.rst.txt index 1d92b78a..0caaf02a 100644 --- a/docs/_sources/astartes.samplers.rst.txt +++ b/docs/_sources/astartes.samplers.rst.txt @@ -1,69 +1,22 @@ astartes.samplers package ========================= -Submodules ----------- - -astartes.samplers.dbscan module -------------------------------- - -.. automodule:: astartes.samplers.dbscan - :members: - :undoc-members: - :show-inheritance: - -astartes.samplers.doptimal module ---------------------------------- - -.. automodule:: astartes.samplers.doptimal - :members: - :undoc-members: - :show-inheritance: - -astartes.samplers.duplex module -------------------------------- - -.. automodule:: astartes.samplers.duplex - :members: - :undoc-members: - :show-inheritance: - -astartes.samplers.kennard\_stone module ---------------------------------------- +Subpackages +----------- -.. automodule:: astartes.samplers.kennard_stone - :members: - :undoc-members: - :show-inheritance: - -astartes.samplers.optisim module --------------------------------- - -.. automodule:: astartes.samplers.optisim - :members: - :undoc-members: - :show-inheritance: - -astartes.samplers.random module -------------------------------- +.. toctree:: + :maxdepth: 4 -.. automodule:: astartes.samplers.random - :members: - :undoc-members: - :show-inheritance: + astartes.samplers.extrapolation + astartes.samplers.interpolation -astartes.samplers.sampler module --------------------------------- - -.. automodule:: astartes.samplers.sampler - :members: - :undoc-members: - :show-inheritance: +Submodules +---------- -astartes.samplers.sphere\_exclusion module +astartes.samplers.abstract\_sampler module ------------------------------------------ -.. automodule:: astartes.samplers.sphere_exclusion +.. automodule:: astartes.samplers.abstract_sampler :members: :undoc-members: :show-inheritance: diff --git a/docs/_sources/astartes.utils.rst.txt b/docs/_sources/astartes.utils.rst.txt new file mode 100644 index 00000000..729aa702 --- /dev/null +++ b/docs/_sources/astartes.utils.rst.txt @@ -0,0 +1,61 @@ +astartes.utils package +====================== + +Submodules +---------- + +astartes.utils.array\_type\_helpers module +------------------------------------------ + +.. automodule:: astartes.utils.array_type_helpers + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.exceptions module +-------------------------------- + +.. automodule:: astartes.utils.exceptions + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.fast\_kennard\_stone module +------------------------------------------ + +.. automodule:: astartes.utils.fast_kennard_stone + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.sampler\_factory module +-------------------------------------- + +.. automodule:: astartes.utils.sampler_factory + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.user\_utils module +--------------------------------- + +.. automodule:: astartes.utils.user_utils + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.warnings module +------------------------------ + +.. automodule:: astartes.utils.warnings + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt index 6b398a99..75ed3a60 100644 --- a/docs/_sources/index.rst.txt +++ b/docs/_sources/index.rst.txt @@ -1,5 +1,5 @@ .. astartes documentation master file, created by - sphinx-quickstart on Fri Jul 9 14:25:42 2021. + sphinx-quickstart on Fri Jul 9 14:25:42 2022. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. @@ -11,6 +11,8 @@ astartes documentation :caption: Contents: README + CONTRIBUTING + sklearn_to_astartes modules diff --git a/docs/_sources/modules.rst.txt b/docs/_sources/modules.rst.txt index 5ec05fd6..831c4b4f 100644 --- a/docs/_sources/modules.rst.txt +++ b/docs/_sources/modules.rst.txt @@ -5,5 +5,4 @@ astartes :maxdepth: 4 astartes - setup test diff --git a/docs/_sources/sklearn_to_astartes.rst.txt b/docs/_sources/sklearn_to_astartes.rst.txt new file mode 100644 index 00000000..fa5248f3 --- /dev/null +++ b/docs/_sources/sklearn_to_astartes.rst.txt @@ -0,0 +1,180 @@ + +Transitioning from ``sklearn`` to ``astartes`` +====================================================== + +Step 1. Installation +-------------------- + +``astartes`` has been designed to rely on (1) as few packages as possible and (2) packages which are already likely to be installed in a Machine Learning (ML) Python workflow (i.e. Numpy and Sklearn). Because of this, ``astartes`` should be compatible with your *existing* workflow such as a conda environment. + +To install ``astartes`` for general ML use (the sampling of arbitrary vectors): **\ ``pip install astartes``\ ** + +For users in cheminformatics, ``astartes`` has an optional add-on that includes featurization as part of the sampling. To install, type **\ ``pip install 'astartes[molecules]'``\ **. With this extra install, ``astartes`` uses `\ ``AIMSim`` `_ to encode SMILES strings as feature vectors. The SMILES strings are parsed into molecular graphs using RDKit and then sampled with a single function call: ``train_test_split_molecules``. + + +* If your workflow already has a featurization scheme in place (i.e. you already have a vector representation of your chemical of interest), you can directly use ``train_test_split`` (though we invite you to explore the many molecular descriptors made available through AIMSim). + +Step 2. Changing the ``import`` Statement +--------------------------------------------- + +In one of the first few lines of your Python script, you have the line ``from sklearn.model_selection import train_test_split``. To switch to using ``astartes`` change this line to ``from astartes import train_test_split``. + +That's it! You are now using ``astartes``. + +If you were just calling ``train_test_split(X, y)``\ , your script should now work in the exact same way as ``sklearn`` with no changes required. + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + random_state=42, + ) + +*becomes* + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + random_state=42, + ) + +But we encourage you to try one of our many other samplers (see below)! + +Step 3. Specifying an Algorithmic Sampler +----------------------------------------- + +By default (for interoperability), ``astartes`` will use a random sampler to produce train/test splits - but the real value of ``astartes`` is in the algorithmic sampling algorithms it implements. Check out the `README for a complete list of available algorithms `_ and how to call and customize them. + +If you existing call to ``train_test_split`` looks like this: + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + ) + +and you want to try out using Kennard-Stone sampling, switch it to this: + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + sampler="kennard_stone", + ) + +That's it! + +Step 4. Passing Keyword Arguments +--------------------------------- + +All of the arguments to the ``sklearn``\ 's ``train_test_split`` can still be passed to ``astartes``\ ' ``train_test_split``\ : + +.. code-block:: python + + X_train, X_test, y_train, y_test, labels_train, labels_test = train_test_split( + X, + y, + labels, + train_size = 0.75, + test_size = 0.25, + sampler = "kmeans", + hopts = {"n_clusters": 4}, + ) + +Some samplers have tunable hyperparameters that allow you to more finely control their behavior. To do this with Sphere Exclusion, for example, switch your call to this: + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + sampler="sphere_exclusion", + hopts={"distance_cutoff":0.15}, + ) + +Step 5. Useful ``astartes`` Features +---------------------------------------- + +``return_indices``\ : Improve Code Clarity +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are circumstances where the indices of the train/test data can be useful (for example, if ``y`` or ``labels`` are large, memory-intense objects), and there is no way to directly return these indices in ``sklearn``. ``astartes`` will return the sampling splits themselves by default, but it can also return the indices for the user to manipulate according to their needs: + +.. code-block:: python + + X_train, X_test, y_train, y_test, labels_train, labels_test = train_test_split( + X, + y, + labels, + return_indices = False, + ) + +*could instead be* + +.. code-block:: python + + X_train, X_test, y_train, y_test, labels_train, labels_test, indices_train, indices_test = train_test_split( + X, + y, + labels, + return_indices = True, + ) + +If ``y`` or ``labels`` were large, memory-intense objects it could be beneficial to *not* pass them in to ``train_test_split`` and instead separate the existing lists later using the returned indices. + +``train_val_test_split``\ : More Rigorous ML +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Behind the scenes, ``train_test_split`` is actually just a one-line function that calls the real workhorse of ``astartes`` - ``train_val_test_split``\ : + +.. code-block:: python + + def train_test_split( + X: np.array, + ... + return_indices: bool = False, + ): + return train_val_test_split( + X, y, labels, train_size, 0, test_size, sampler, hopts, return_indices + ) + +The function call to ``train_val_test_split`` is identical to ``train_test_split`` and supports all the same samplers and hyperparameters, except for one additional keyword argument ``val_size``\ : + +.. code-block:: python + + def train_val_test_split( + X: np.array, + y: np.array = None, + labels: np.array = None, + train_size: float = 0.8, + val_size: float = 0.1, + test_size: float = 0.1, + sampler: str = "random", + hopts: dict = {}, + return_indices: bool = False, + ): + +When called, this will return *three* arrays from ``X``\ , ``y``\ , and ``labels`` (or three arrays of indices, if ``return_indices=True``\ ) rather than the usual two, according to the values given for ``train_size``\ , ``val_size``\ , and ``test_size`` in the function call. + +.. code-block:: python + + X_train, X_val, X_test, y_train, y_val, y_test = train_val_test_split( + X, + y, + train_size: float = 0.8, + val_size: float = 0.1, + test_size: float = 0.1, + ) + +For truly rigorous ML modeling, the validation set should be used for hyperparameter tuning and the test set held out until the *very final* change has been made to the model to get a true sense of its performance. For better or for worse, this is *not* the current standard for ML modeling, but the authors believe it should be. + +Custom Warnings: ``ImperfectSplittingWarning`` and ``NormalizationWarning`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the event that your requested train/validation/test split is not mathematically possible given the dimensions of the input data (i.e. you request 50/25/25 but have 101 data points), ``astartes`` will warn you during runtime that it has occurred. ``sklearn`` simply moves on quietly, and while this is fine *most* of the time, the authors felt it prudent to warn the user. +When entering a train/validation/test split, ``astartes`` will check that it is normalized and make it so if not, warning the user during runtime. This will hopefully help prevent head-scratching hours of debugging. diff --git a/docs/_sources/test.functional.rst.txt b/docs/_sources/test.functional.rst.txt new file mode 100644 index 00000000..0c1189a2 --- /dev/null +++ b/docs/_sources/test.functional.rst.txt @@ -0,0 +1,29 @@ +test.functional package +======================= + +Submodules +---------- + +test.functional.test\_astartes module +------------------------------------- + +.. automodule:: test.functional.test_astartes + :members: + :undoc-members: + :show-inheritance: + +test.functional.test\_molecules module +-------------------------------------- + +.. automodule:: test.functional.test_molecules + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.functional + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/test.regression.rst.txt b/docs/_sources/test.regression.rst.txt new file mode 100644 index 00000000..c3cb03bb --- /dev/null +++ b/docs/_sources/test.regression.rst.txt @@ -0,0 +1,21 @@ +test.regression package +======================= + +Submodules +---------- + +test.regression.test\_regression module +--------------------------------------- + +.. automodule:: test.regression.test_regression + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.regression + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/test.rst.txt b/docs/_sources/test.rst.txt new file mode 100644 index 00000000..9fca9975 --- /dev/null +++ b/docs/_sources/test.rst.txt @@ -0,0 +1,20 @@ +test package +============ + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test.functional + test.regression + test.unit + +Module contents +--------------- + +.. automodule:: test + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/test.unit.rst.txt b/docs/_sources/test.unit.rst.txt new file mode 100644 index 00000000..d11aa2eb --- /dev/null +++ b/docs/_sources/test.unit.rst.txt @@ -0,0 +1,19 @@ +test.unit package +================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test.unit.samplers + test.unit.utils + +Module contents +--------------- + +.. automodule:: test.unit + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/test.unit.samplers.extrapolative.rst.txt b/docs/_sources/test.unit.samplers.extrapolative.rst.txt new file mode 100644 index 00000000..cd6b17ef --- /dev/null +++ b/docs/_sources/test.unit.samplers.extrapolative.rst.txt @@ -0,0 +1,61 @@ +test.unit.samplers.extrapolative package +======================================== + +Submodules +---------- + +test.unit.samplers.extrapolative.test\_DBSCAN module +---------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_DBSCAN + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_Scaffold module +------------------------------------------------------ + +.. automodule:: test.unit.samplers.extrapolative.test_Scaffold + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_kmeans module +---------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_kmeans + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_optisim module +----------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_optisim + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_sphere\_exclusion module +--------------------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_sphere_exclusion + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_time\_based module +--------------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_time_based + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.unit.samplers.extrapolative + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/test.unit.samplers.interpolative.rst.txt b/docs/_sources/test.unit.samplers.interpolative.rst.txt new file mode 100644 index 00000000..812af5a9 --- /dev/null +++ b/docs/_sources/test.unit.samplers.interpolative.rst.txt @@ -0,0 +1,37 @@ +test.unit.samplers.interpolative package +======================================== + +Submodules +---------- + +test.unit.samplers.interpolative.test\_kennard\_stone module +------------------------------------------------------------ + +.. automodule:: test.unit.samplers.interpolative.test_kennard_stone + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.interpolative.test\_random module +---------------------------------------------------- + +.. automodule:: test.unit.samplers.interpolative.test_random + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.interpolative.test\_spxy module +-------------------------------------------------- + +.. automodule:: test.unit.samplers.interpolative.test_spxy + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.unit.samplers.interpolative + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/test.unit.samplers.rst.txt b/docs/_sources/test.unit.samplers.rst.txt new file mode 100644 index 00000000..dc112797 --- /dev/null +++ b/docs/_sources/test.unit.samplers.rst.txt @@ -0,0 +1,19 @@ +test.unit.samplers package +========================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test.unit.samplers.extrapolative + test.unit.samplers.interpolative + +Module contents +--------------- + +.. automodule:: test.unit.samplers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_sources/test.unit.utils.rst.txt b/docs/_sources/test.unit.utils.rst.txt new file mode 100644 index 00000000..d4b96cf4 --- /dev/null +++ b/docs/_sources/test.unit.utils.rst.txt @@ -0,0 +1,37 @@ +test.unit.utils package +======================= + +Submodules +---------- + +test.unit.utils.test\_convert\_to\_array module +----------------------------------------------- + +.. automodule:: test.unit.utils.test_convert_to_array + :members: + :undoc-members: + :show-inheritance: + +test.unit.utils.test\_sampler\_factory module +--------------------------------------------- + +.. automodule:: test.unit.utils.test_sampler_factory + :members: + :undoc-members: + :show-inheritance: + +test.unit.utils.test\_utils module +---------------------------------- + +.. automodule:: test.unit.utils.test_utils + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.unit.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/_static/_sphinx_javascript_frameworks_compat.js b/docs/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000..81415803 --- /dev/null +++ b/docs/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/docs/_static/sphinx_highlight.js b/docs/_static/sphinx_highlight.js new file mode 100644 index 00000000..8a96c69a --- /dev/null +++ b/docs/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/docs/astartes.doctree b/docs/astartes.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d4350cb610f18278afc7cba75b2a4fea2428d2c0 GIT binary patch literal 120192 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 M@#X6j^Np$h4*+Q@)c^nh literal 0 HcmV?d00001 diff --git a/docs/astartes.html b/docs/astartes.html new file mode 100644 index 00000000..6abbcbc5 --- /dev/null +++ b/docs/astartes.html @@ -0,0 +1,388 @@ + + + + + + + astartes package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

astartes package

+
+

Subpackages

+
+ +
+
+
+

Submodules

+
+
+

astartes.main module

+
+
+astartes.main.train_test_split(X: array, y: array | None = None, labels: array | None = None, train_size: float = 0.75, test_size: float | None = None, sampler: str = 'random', random_state: int | None = None, hopts: dict = {}, return_indices: bool = False)
+

Deterministic train_test_splitting of arbitrary arrays.

+
+
Parameters:
+
    +
  • X (np.array) – Numpy array of feature vectors.

  • +
  • y (np.array, optional) – Targets corresponding to X, must be of same size. Defaults to None.

  • +
  • labels (np.array, optional) – Labels corresponding to X, must be of same size. Defaults to None.

  • +
  • train_size (float, optional) – Fraction of dataset to use in training set. Defaults to 0.75.

  • +
  • test_size (float, optional) – Fraction of dataset to use in test set. Defaults to None.

  • +
  • sampler (str, optional) – Sampler to use, see IMPLEMENTED_INTER/EXTRAPOLATION_SAMPLERS. Defaults to “random”.

  • +
  • random_state (int, optional) – The random seed used throughout astartes.

  • +
  • hopts (dict, optional) – Hyperparameters for the sampler used above. Defaults to {}.

  • +
  • return_indices (bool, optional) – True to return indices of train/test instead of values. Defaults to False.

  • +
+
+
Returns:
+

X, y, and labels train/val/test data, or indices.

+
+
Return type:
+

np.array

+
+
+
+ +
+
+astartes.main.train_val_test_split(X: array | DataFrame, y: array | Series | None = None, labels: array | Series | None = None, train_size: float = 0.8, val_size: float = 0.1, test_size: float = 0.1, sampler: str = 'random', random_state: int | None = None, hopts: dict = {}, return_indices: bool = False)
+

Deterministic train_test_splitting of arbitrary arrays.

+
+
Parameters:
+
    +
  • X (np.array, pd.DataFrame) – Numpy array or pandas DataFrame of feature vectors.

  • +
  • y (np.array, pd.Series, optional) – Targets corresponding to X, must be of same size. Defaults to None.

  • +
  • labels (np.array, pd.Series, optional) – Labels corresponding to X, must be of same size. Defaults to None.

  • +
  • train_size (float, optional) – Fraction of dataset to use in training set. Defaults to 0.8.

  • +
  • val_size (float, optional) – Fraction of dataset to use in validation set. Defaults to 0.1.

  • +
  • test_size (float, optional) – Fraction of dataset to use in test set. Defaults to 0.1.

  • +
  • sampler (str, optional) – Sampler to use, see IMPLEMENTED_INTER/EXTRAPOLATION_SAMPLERS. Defaults to “random”.

  • +
  • random_state (int, optional) – The random seed used throughout astartes.

  • +
  • hopts (dict, optional) – Hyperparameters for the sampler used above. Defaults to {}.

  • +
  • return_indices (bool, optional) – True to return indices of train/test after values. Defaults to False.

  • +
+
+
Returns:
+

X, y, and labels train/val/test data, or indices.

+
+
Return type:
+

np.array(s)

+
+
+
+ +
+
+

astartes.molecules module

+
+
+astartes.molecules.train_test_split_molecules(molecules: array, y: array | None = None, labels: array | None = None, train_size: float = 0.75, test_size: float | None = None, sampler: str = 'random', random_state: int | None = None, hopts: dict = {}, fingerprint: str = 'morgan_fingerprint', fprints_hopts: dict = {}, return_indices: bool = False)
+

Deterministic train/test splitting of molecules (SMILES strings or RDKit objects).

+
+
Parameters:
+
    +
  • molecules (np.array) – List of SMILES strings or RDKit molecule objects representing molecules or reactions.

  • +
  • y (np.array, optional) – Targets corresponding to SMILES, must be of same size. Defaults to None.

  • +
  • labels (np.array, optional) – Labels corresponding to SMILES, must be of same size. Defaults to None.

  • +
  • train_size (float, optional) – Fraction of dataset to use in training (test+train~1). Defaults to 0.75.

  • +
  • test_size (float, optional) – Fraction of dataset to use in test set. Defaults to None.

  • +
  • sampler (str, optional) – Sampler to use, see IMPLEMENTED_INTER/EXTRAPOLATION_SAMPLERS. Defaults to “random”.

  • +
  • random_state (int, optional) – The random seed used throughout astartes. Defaults to None.

  • +
  • hopts (dict, optional) – Hyperparameters for the sampler used above. Defaults to {}.

  • +
  • fingerprint (str, optional) – Molecular fingerprint to be used from AIMSim. Defaults to “morgan_fingerprint”.

  • +
  • fprints_hopts (dict, optional) – Hyperparameters for AIMSim featurization. Defaults to {}.

  • +
  • return_indices (bool, optional) – True to return indices of train/test after the values. Defaults to False.

  • +
+
+
Returns:
+

X, y, and labels train/test data, or indices.

+
+
Return type:
+

np.array

+
+
+
+ +
+
+astartes.molecules.train_val_test_split_molecules(molecules: array, y: array | None = None, labels: array | None = None, train_size: float = 0.8, val_size: float = 0.1, test_size: float = 0.1, sampler: str = 'random', random_state: int | None = None, hopts: dict = {}, fingerprint: str = 'morgan_fingerprint', fprints_hopts: dict = {}, return_indices: bool = False)
+

Deterministic train_test_splitting of molecules (SMILES strings or RDKit objects).

+
+
Parameters:
+
    +
  • molecules (np.array) – List of SMILES strings or RDKit molecule objects representing molecules or reactions.

  • +
  • y (np.array, optional) – Targets corresponding to SMILES, must be of same size. Defaults to None.

  • +
  • labels (np.array, optional) – Labels corresponding to SMILES, must be of same size. Defaults to None.

  • +
  • train_size (float, optional) – Fraction of dataset to use in training set. Defaults to 0.8.

  • +
  • val_size (float, optional) – Fraction of dataset to use in validation set. Defaults to 0.1.

  • +
  • test_size (float, optional) – Fraction of dataset to use in test set. Defaults to 0.1.

  • +
  • sampler (str, optional) – Sampler to use, see IMPLEMENTED_INTER/EXTRAPOLATION_SAMPLERS. Defaults to “random”.

  • +
  • random_state (int, optional) – The random seed used throughout astartes. Defaults to 42.

  • +
  • hopts (dict, optional) – Hyperparameters for the sampler used above. Defaults to {}.

  • +
  • fingerprint (str, optional) – Molecular fingerprint to be used from AIMSim. Defaults to “morgan_fingerprint”.

  • +
  • fprints_hopts (dict, optional) – Hyperparameters for AIMSim featurization. Defaults to {}.

  • +
  • return_indices (bool, optional) – True to return indices of train/test after the values. Defaults to False.

  • +
+
+
Returns:
+

X, y, and labels train/val/test data, or indices.

+
+
Return type:
+

np.array

+
+
+
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/astartes.rst b/docs/astartes.rst new file mode 100644 index 00000000..4af4818c --- /dev/null +++ b/docs/astartes.rst @@ -0,0 +1,38 @@ +astartes package +================ + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + astartes.samplers + astartes.utils + +Submodules +---------- + +astartes.main module +-------------------- + +.. automodule:: astartes.main + :members: + :undoc-members: + :show-inheritance: + +astartes.molecules module +------------------------- + +.. automodule:: astartes.molecules + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/astartes.samplers.doctree b/docs/astartes.samplers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..67800c1fc83c33a97e7230b499cfac488febb5cc GIT binary patch literal 22754 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 E0H{uEsQ>@~ literal 0 HcmV?d00001 diff --git a/docs/astartes.samplers.extrapolation.doctree b/docs/astartes.samplers.extrapolation.doctree new file mode 100644 index 0000000000000000000000000000000000000000..3dacd8ee984e4ed39c4e8dec50462615c4327f49 GIT binary patch literal 56122 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 literal 0 HcmV?d00001 diff --git a/docs/astartes.samplers.extrapolation.html b/docs/astartes.samplers.extrapolation.html new file mode 100644 index 00000000..ecd1c266 --- /dev/null +++ b/docs/astartes.samplers.extrapolation.html @@ -0,0 +1,334 @@ + + + + + + + astartes.samplers.extrapolation package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

astartes.samplers.extrapolation package

+
+

Submodules

+
+
+

astartes.samplers.extrapolation.dbscan module

+
+
+class astartes.samplers.extrapolation.dbscan.DBSCAN(X, y, labels, configs)
+

Bases: AbstractSampler

+
+ +
+
+

astartes.samplers.extrapolation.kmeans module

+
+
+class astartes.samplers.extrapolation.kmeans.KMeans(X, y, labels, configs)
+

Bases: AbstractSampler

+
+ +
+
+

astartes.samplers.extrapolation.optisim module

+

The Optimizable K-Dissimilarity Selection (OptiSim) algorithm, as originally +described by Clark (https://pubs.acs.org/doi/full/10.1021/ci970282v), adapted +to work for arbitrary distance metrics.

+

The original algorithm: +1. Initialization

+
+
    +
  • Take a featurized dataset and select an arbitrary starting data point for +the selection set.

  • +
  • Treat the remaining data as ‘candidates’.

  • +
  • Create an empty ‘recycling bin’.

  • +
  • Create an empty subsample set.

  • +
  • Create an empty selection set.

  • +
+
+
    +
  1. Remove a random point from the candidates.

  2. +
+
+
    +
  • if it has a similarity greater than a given cutoff to any of the members of the selection set,

  • +
+

recycle it (or conversely, if it is within a cutoff distance) +- otherwise, add to subsample set

+
+
    +
  1. Repeat 2 until one of two conditions is met:

  2. +
+
+
    +
  1. The subsample reaches the pre-determined maximum size K or

  2. +
  3. The candidates are exhausted.

  4. +
+
+

4. If Step 3 resulted in condition b, move all data from recycling bin and go +to Step 2.

+

5. If subsample is empty, quit (all remaining candidates are similar, the +most dissimilar data points have already been identified)

+

6. Pick the most dissimilar (relative to data points already in selection set) +point in the subsample and add it to the selection set.

+
    +
  1. Move the remaining points in the subsample to the recycling bin.

  2. +
  3. If size(selection set) is sufficient, quit. Otherwise, go to Step 2.

  4. +
+

As suggested in the original paper, the members of the selection set are then +used as cluster centers, and we assign every element in the dataset to belong +to the cluster containing the selection set member to which it is the most +similar. To implement this step, use scipy.spatial.distance.cdist.

+

This algorithm seems like it might introduce an infinite loop if the subsample +is not filled and all of the remaining candidates are within the cutoff and cannot +be added. Might need a stop condition here? Unless the empyting of the recycling bin +will somehow fix this. Also possible that one would never have a partially filled +subsample after looking at the full dataset since it is more probable that ALL the +points would be rejected and the subsample would be empty.

+

Likely just check for no more points being possible to fit into the subsample, and +exit if that is the case.

+
+
+class astartes.samplers.extrapolation.optisim.OptiSim(X, y, labels, configs)
+

Bases: AbstractSampler

+
+
+get_dist(i, j)
+

Calculates pdist and returns distance between two samples

+
+ +
+
+move_item(item, source_set, destintation_set)
+

Moves item from source_set to destination_set

+
+ +
+
+rchoose(set)
+

Choose a random element from a set with self._rng

+
+ +
+ +
+
+

astartes.samplers.extrapolation.scaffold module

+

This sampler partitions the data based on the Bemis-Murcko scaffold function as implemented in RDKit. +Bemis, G. W.; Murcko, M. A. The Properties of Known Drugs. 1. Molecular Frameworks. J. Med. Chem. 1996, 39, 2887−2893. +Landrum, G. et al. RDKit: Open-Source Cheminformatics; 2006; https://www.rdkit.org.

+

The goal is to cluster molecules that share the same scaffold. +Later, these clusters will be assigned to training, validation, and testing split +to create data splits that will measure extrapolation by testing on scaffolds +that are not in the training set.

+
+
+class astartes.samplers.extrapolation.scaffold.Scaffold(X, y, labels, configs)
+

Bases: AbstractSampler

+
+
+generate_bemis_murcko_scaffold(mol, include_chirality=False)
+

Compute the Bemis-Murcko scaffold for an RDKit molecule.

+
+
Params:

mol: A smiles string or an RDKit molecule. +include_chirality: Whether to include chirality.

+
+
+
+
Returns:
+

Bemis-Murcko scaffold

+
+
+
+ +
+
+scaffold_to_smiles(mols)
+

Computes scaffold for each smiles string and returns a mapping from scaffolds to sets of smiles.

+
+
Params:

mols: A list of smiles strings or RDKit molecules.

+
+
+
+
Returns:
+

A dictionary mapping each unique scaffold to all smiles (or smiles indices) which have that scaffold.

+
+
+
+ +
+
+str_to_mol(string)
+

Converts an InChI or SMILES string to an RDKit molecule.

+
+
Params:

string: The InChI or SMILES string.

+
+
+
+
Returns:
+

An RDKit molecule.

+
+
+
+ +
+ +
+
+

astartes.samplers.extrapolation.sphere_exclusion module

+

The Sphere Exclusion clustering algorithm.

+

This re-implementation draws from this blog post on the RDKit blog, +though abstracted to work for arbitrary feature vectors: +http://rdkit.blogspot.com/2020/11/sphere-exclusion-clustering-with-rdkit.html +As well as this paper: +https://www.daylight.com/cheminformatics/whitepapers/ClusteringWhitePaper.pdf

+

But instead of using tanimoto similarity, which has a domain between zero and +one, it uses euclidian distance to enable processing arbitrary valued +vectors.

+
+
+class astartes.samplers.extrapolation.sphere_exclusion.SphereExclusion(X, y, labels, configs)
+

Bases: AbstractSampler

+
+ +
+
+

astartes.samplers.extrapolation.time_based module

+
+
+class astartes.samplers.extrapolation.time_based.TimeBased(X, y, labels, configs)
+

Bases: AbstractSampler

+
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/astartes.samplers.extrapolation.rst b/docs/astartes.samplers.extrapolation.rst new file mode 100644 index 00000000..6fd2f0b8 --- /dev/null +++ b/docs/astartes.samplers.extrapolation.rst @@ -0,0 +1,61 @@ +astartes.samplers.extrapolation package +======================================= + +Submodules +---------- + +astartes.samplers.extrapolation.dbscan module +--------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.dbscan + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.kmeans module +--------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.kmeans + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.optisim module +---------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.optisim + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.scaffold module +----------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.scaffold + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.sphere\_exclusion module +-------------------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.sphere_exclusion + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.extrapolation.time\_based module +-------------------------------------------------- + +.. automodule:: astartes.samplers.extrapolation.time_based + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes.samplers.extrapolation + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/astartes.samplers.html b/docs/astartes.samplers.html new file mode 100644 index 00000000..36b7f9b7 --- /dev/null +++ b/docs/astartes.samplers.html @@ -0,0 +1,272 @@ + + + + + + + astartes.samplers package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

astartes.samplers package

+
+

Subpackages

+ +
+
+

Submodules

+
+
+

astartes.samplers.abstract_sampler module

+

Abstract Sampling class

+
+
+class astartes.samplers.abstract_sampler.AbstractSampler(X, y, labels, configs)
+

Bases: ABC

+

Abstract Base Class for all samplers.

+
+
+__init__(X, y, labels, configs)
+

Copies X, y, labels, and configs into class attributes and then calls sampler.

+
+ +
+
+get_clusters()
+

Getter for the cluster labels.

+
+
Returns:
+

Cluster labels.

+
+
Return type:
+

np.array

+
+
+
+ +
+
+get_config(key, default=None)
+

Getter to sampler._configs

+
+
Parameters:
+
    +
  • key (str) – String parameter for the sampler.

  • +
  • default (any, optional) – Default to return if key not present. Defaults to None.

  • +
+
+
Returns:
+

value at provided key, or else default.

+
+
Return type:
+

any

+
+
+
+ +
+
+get_sample_idxs(n_samples)
+

Get idxs of samples.

+
+ +
+
+get_sorted_cluster_counter(max_shufflable_size=None)
+

Return a dict containing cluster_id: number of members sorted by number +of members, ascending

+

if max_shufflable_size is not None, clusters below the passed size will be +shuffled into a new order according to random_state in hopts

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/astartes.samplers.interpolation.doctree b/docs/astartes.samplers.interpolation.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ca0fa95702f94cf49ee721957dc98719b53edf37 GIT binary patch literal 16486 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 + + + + + + astartes.samplers.interpolation package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

astartes.samplers.interpolation package

+
+

Submodules

+
+
+

astartes.samplers.interpolation.kennardstone module

+
+
+class astartes.samplers.interpolation.kennardstone.KennardStone(X, y, labels, configs)
+

Bases: AbstractSampler

+
+ +
+
+

astartes.samplers.interpolation.random_split module

+
+
+class astartes.samplers.interpolation.random_split.Random(X, y, labels, configs)
+

Bases: AbstractSampler

+
+ +
+
+

astartes.samplers.interpolation.spxy module

+

Implements the Sample set Partitioning based on join X-Y distances +algorithm as originally described by Saldanha and coworkers in +“A method for calibration and validation subset partitioning” +doi:10.1016/j.talanta.2005.03.025

+

This implementation has been validated against their original source +code implementation, which can be found in the paper linked above. +The corresponding unit tests reflect the expected output from +the original implemenation. The breaking of ties is different +compared to the original, but this is ultimately a minor and +likely inconsequential difference.

+
+
+class astartes.samplers.interpolation.spxy.SPXY(X, y, labels, configs)
+

Bases: AbstractSampler

+
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/astartes.samplers.interpolation.rst b/docs/astartes.samplers.interpolation.rst new file mode 100644 index 00000000..91f887d4 --- /dev/null +++ b/docs/astartes.samplers.interpolation.rst @@ -0,0 +1,37 @@ +astartes.samplers.interpolation package +======================================= + +Submodules +---------- + +astartes.samplers.interpolation.kennardstone module +--------------------------------------------------- + +.. automodule:: astartes.samplers.interpolation.kennardstone + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.interpolation.random\_split module +---------------------------------------------------- + +.. automodule:: astartes.samplers.interpolation.random_split + :members: + :undoc-members: + :show-inheritance: + +astartes.samplers.interpolation.spxy module +------------------------------------------- + +.. automodule:: astartes.samplers.interpolation.spxy + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes.samplers.interpolation + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/astartes.samplers.rst b/docs/astartes.samplers.rst new file mode 100644 index 00000000..0caaf02a --- /dev/null +++ b/docs/astartes.samplers.rst @@ -0,0 +1,30 @@ +astartes.samplers package +========================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + astartes.samplers.extrapolation + astartes.samplers.interpolation + +Submodules +---------- + +astartes.samplers.abstract\_sampler module +------------------------------------------ + +.. automodule:: astartes.samplers.abstract_sampler + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes.samplers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/astartes.utils.doctree b/docs/astartes.utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..75e477edbb00444b0eaf8e1da05868fea1fb00d3 GIT binary patch literal 136339 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 Ee^12}LjV8( literal 0 HcmV?d00001 diff --git a/docs/astartes.utils.html b/docs/astartes.utils.html new file mode 100644 index 00000000..f8e34b8d --- /dev/null +++ b/docs/astartes.utils.html @@ -0,0 +1,527 @@ + + + + + + + astartes.utils package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

astartes.utils package

+
+

Submodules

+
+
+

astartes.utils.array_type_helpers module

+
+
+astartes.utils.array_type_helpers.convert_to_array(obj: object, name: str)
+

Attempt to convert obj named name to a numpy array, with appropriate warnings and exceptions.

+
+
Parameters:
+
    +
  • obj (object) – The item to attempt to convert.

  • +
  • name (str) – Human-readable name for printing.

  • +
+
+
+
+ +
+
+astartes.utils.array_type_helpers.panda_handla(X, y, labels)
+

Helper function to deal with supporting Pandas data types in astartes

+
+
Parameters:
+
    +
  • X (Dataframe) – Features with column names

  • +
  • y (Series) – Targets

  • +
  • labels (Series) – Labels for data

  • +
+
+
Returns:
+

Empty if no pandas types, metadata-filled otherwise

+
+
Return type:
+

dict

+
+
+
+ +
+
+astartes.utils.array_type_helpers.return_helper(sampler_instance, train_idxs, val_idxs, test_idxs, return_indices, output_is_pandas)
+

Convenience function to return the requested arrays appropriately.

+
+
Parameters:
+
    +
  • sampler_instance (sampler) – The fit sampler instance.

  • +
  • test_size (float) – Fraction of data to use in test.

  • +
  • val_size (float) – Fraction of data to use in val.

  • +
  • train_size (float) – Fraction of data to use in train.

  • +
  • return_indices (bool) – Return indices after the value arrays.

  • +
  • output_is_pandas (dict) – metadata about casting to pandas.

  • +
+
+
Returns:
+

Either many arrays or indices in arrays.

+
+
Return type:
+

np.array

+
+
+

Notes

+

This function copies and pastes a lot of code when it could instead +use some loop over (X, y, labels, sampler_instance.get_clusters()) +but such an implementation is more error prone. This is long and +not the prettiest, but it is definitely doing what we want.

+
+ +
+
+

astartes.utils.exceptions module

+

Exceptions used by astartes

+
+
+exception astartes.utils.exceptions.InvalidConfigurationError(message=None)
+

Bases: RuntimeError

+

Used when user-requested split/data would not work.

+
+
+__init__(message=None)
+
+ +
+ +
+
+exception astartes.utils.exceptions.InvalidModelTypeError(message=None)
+

Bases: RuntimeError

+

Used when user-provided model is invalid.

+
+
+__init__(message=None)
+
+ +
+ +
+
+exception astartes.utils.exceptions.MoleculesNotInstalledError(message=None)
+

Bases: RuntimeError

+

Used when attempting to featurize molecules without install.

+
+
+__init__(message=None)
+
+ +
+ +
+
+exception astartes.utils.exceptions.SamplerNotImplementedError(message=None)
+

Bases: RuntimeError

+

Used when attempting to call a non-existent sampler.

+
+
+__init__(message=None)
+
+ +
+ +
+
+exception astartes.utils.exceptions.UncastableInputError(message=None)
+

Bases: RuntimeError

+

Used when X, y, or labels cannot be cast to a np.array.

+
+
+__init__(message=None)
+
+ +
+ +
+
+

astartes.utils.fast_kennard_stone module

+
+
+astartes.utils.fast_kennard_stone.fast_kennard_stone(ks_distance: ndarray) ndarray
+

Implements the Kennard-Stone algorithm

+
+
Parameters:
+

ks_distance (np.ndarray) – Distance matrix

+
+
Returns:
+

Indices in order of Kennard-Stone selection

+
+
Return type:
+

np.ndarray

+
+
+
+ +
+
+

astartes.utils.sampler_factory module

+
+
+class astartes.utils.sampler_factory.SamplerFactory(sampler)
+

Bases: object

+
+
+__init__(sampler)
+

Initialize SamplerFactory and copy a lowercased ‘sampler’ into an attribute.

+
+
Parameters:
+

sampler (string) – The desired sampler.

+
+
+
+ +
+
+get_sampler(X, y, labels, hopts)
+

Instantiate (which also performs fitting) and return the sampler.

+
+
Parameters:
+
    +
  • X (np.array) – Feature array.

  • +
  • y (np.array) – Target array.

  • +
  • labels (np.array) – Label array.

  • +
  • hopts (dict) – Hyperparameters for the sampler.

  • +
+
+
Raises:
+

SamplerNotImplementedError – Raised when an non-existent or not yet implemented sampler is requested.

+
+
Returns:
+

The fit sampler instance.

+
+
Return type:
+

astartes.sampler

+
+
+
+ +
+ +
+
+

astartes.utils.user_utils module

+
+
+astartes.utils.user_utils.display_results_as_table(error_dict)
+

Helper function to print a dictionary as a neat tabulate

+
+ +
+
+astartes.utils.user_utils.generate_regression_results_dict(sklearn_model, X, y, samplers=['random'], random_state=0, samplers_hopts={}, train_size=0.8, val_size=0.1, test_size=0.1, print_results=False, additional_metrics={})
+

Helper function to train a sklearn model using the provided data +and provided sampler types.

+
+
Parameters:
+
    +
  • X (np.array, pd.DataFrame) – Numpy array or pandas DataFrame of feature vectors.

  • +
  • y (np.array, pd.Series) – Targets corresponding to X, must be of same size.

  • +
  • train_size (float, optional) – Fraction of dataset to use in training set. Defaults to 0.8.

  • +
  • val_size (float, optional) – Fraction of dataset to use in validation set. Defaults to 0.1.

  • +
  • test_size (float, optional) – Fraction of dataset to use in test set. Defaults to 0.1.

  • +
  • random_state (int, optional) – The random seed used throughout astartes.

  • +
  • samplers_hopts (dict, optional) – Should be a dictionary of dictionaries with the keys specifying +the sampler and the values being another dictionary with the +corresponding hyperparameters. Defaults to {}.

  • +
  • print_results (bool, optional) – whether to print the resulting dictionary as a neat table

  • +
  • additional_metrics (dict, optional) – mapping of name (str) to metric (func) for additional metrics +such as those in sklearn.metrics or user-provided functions

  • +
+
+
Returns:
+

+
nested dictionary with the format of
+
{
+
sampler: {
+
‘mae’:{

‘train’: [], +‘val’: [], +‘test’: [],

+
+
+

}, +‘rmse’:{

+
+

’train’: [], +‘val’: [], +‘test’: [],

+
+

}, +‘R2’:{

+
+

’train’: [], +‘val’: [], +‘test’: [],

+
+

},

+
+
+

},

+
+
+

}

+
+
+

+
+
Return type:
+

dict

+
+
+
+ +
+
+

astartes.utils.warnings module

+

Warnings used by astartes

+
+
+exception astartes.utils.warnings.ConversionWarning(message=None)
+

Bases: RuntimeWarning

+

Used when passed data is not a numpy array.

+
+
+__init__(message=None)
+
+ +
+ +
+
+exception astartes.utils.warnings.ImperfectSplittingWarning(message=None)
+

Bases: RuntimeWarning

+

Used when a sampler cannot match requested splits.

+
+
+__init__(message=None)
+
+ +
+ +
+
+exception astartes.utils.warnings.NoMatchingScaffold(message=None)
+

Bases: Warning

+

Used when an RDKit molecule does not match any +Bemis-Murcko scaffold and returns an empty string.

+
+
+__init__(message=None)
+
+ +
+ +
+
+exception astartes.utils.warnings.NormalizationWarning(message=None)
+

Bases: RuntimeWarning

+

Used when a requested split does not add to 1.

+
+
+__init__(message=None)
+
+ +
+ +
+
+

Module contents

+
+
+astartes.utils.generate_regression_results_dict(sklearn_model, X, y, samplers=['random'], random_state=0, samplers_hopts={}, train_size=0.8, val_size=0.1, test_size=0.1, print_results=False, additional_metrics={})
+

Helper function to train a sklearn model using the provided data +and provided sampler types.

+
+
Parameters:
+
    +
  • X (np.array, pd.DataFrame) – Numpy array or pandas DataFrame of feature vectors.

  • +
  • y (np.array, pd.Series) – Targets corresponding to X, must be of same size.

  • +
  • train_size (float, optional) – Fraction of dataset to use in training set. Defaults to 0.8.

  • +
  • val_size (float, optional) – Fraction of dataset to use in validation set. Defaults to 0.1.

  • +
  • test_size (float, optional) – Fraction of dataset to use in test set. Defaults to 0.1.

  • +
  • random_state (int, optional) – The random seed used throughout astartes.

  • +
  • samplers_hopts (dict, optional) – Should be a dictionary of dictionaries with the keys specifying +the sampler and the values being another dictionary with the +corresponding hyperparameters. Defaults to {}.

  • +
  • print_results (bool, optional) – whether to print the resulting dictionary as a neat table

  • +
  • additional_metrics (dict, optional) – mapping of name (str) to metric (func) for additional metrics +such as those in sklearn.metrics or user-provided functions

  • +
+
+
Returns:
+

+
nested dictionary with the format of
+
{
+
sampler: {
+
‘mae’:{

‘train’: [], +‘val’: [], +‘test’: [],

+
+
+

}, +‘rmse’:{

+
+

’train’: [], +‘val’: [], +‘test’: [],

+
+

}, +‘R2’:{

+
+

’train’: [], +‘val’: [], +‘test’: [],

+
+

},

+
+
+

},

+
+
+

}

+
+
+

+
+
Return type:
+

dict

+
+
+
+ +
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/astartes.utils.rst b/docs/astartes.utils.rst new file mode 100644 index 00000000..729aa702 --- /dev/null +++ b/docs/astartes.utils.rst @@ -0,0 +1,61 @@ +astartes.utils package +====================== + +Submodules +---------- + +astartes.utils.array\_type\_helpers module +------------------------------------------ + +.. automodule:: astartes.utils.array_type_helpers + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.exceptions module +-------------------------------- + +.. automodule:: astartes.utils.exceptions + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.fast\_kennard\_stone module +------------------------------------------ + +.. automodule:: astartes.utils.fast_kennard_stone + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.sampler\_factory module +-------------------------------------- + +.. automodule:: astartes.utils.sampler_factory + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.user\_utils module +--------------------------------- + +.. automodule:: astartes.utils.user_utils + :members: + :undoc-members: + :show-inheritance: + +astartes.utils.warnings module +------------------------------ + +.. automodule:: astartes.utils.warnings + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: astartes.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/environment.pickle b/docs/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..976511a63df023712751f2e8760ee7d664d9ccc3 GIT binary patch literal 1163609 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
oB-8a0TPppCq*bsak{I@t1i`95XoKNKi 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 T4rRml&M}GPOSZ73me~IT1U??k literal 0 HcmV?d00001 diff --git a/docs/genindex.html b/docs/genindex.html new file mode 100644 index 00000000..a12747d3 --- /dev/null +++ b/docs/genindex.html @@ -0,0 +1,965 @@ + + + + + + Index — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Index

+ +
+ _ + | A + | C + | D + | F + | G + | I + | K + | M + | N + | O + | P + | R + | S + | T + | U + +
+

_

+ + +
+ +

A

+ + + +
    +
  • AbstractSampler (class in astartes.samplers.abstract_sampler) +
  • +
  • + astartes + +
  • +
  • + astartes.main + +
  • +
  • + astartes.molecules + +
  • +
  • + astartes.samplers + +
  • +
  • + astartes.samplers.abstract_sampler + +
  • +
  • + astartes.samplers.extrapolation + +
  • +
  • + astartes.samplers.extrapolation.dbscan + +
  • +
  • + astartes.samplers.extrapolation.kmeans + +
  • +
  • + astartes.samplers.extrapolation.optisim + +
  • +
  • + astartes.samplers.extrapolation.scaffold + +
  • +
  • + astartes.samplers.extrapolation.sphere_exclusion + +
  • +
    +
  • + astartes.samplers.extrapolation.time_based + +
  • +
  • + astartes.samplers.interpolation + +
  • +
  • + astartes.samplers.interpolation.kennardstone + +
  • +
  • + astartes.samplers.interpolation.random_split + +
  • +
  • + astartes.samplers.interpolation.spxy + +
  • +
  • + astartes.utils + +
  • +
  • + astartes.utils.array_type_helpers + +
  • +
  • + astartes.utils.exceptions + +
  • +
  • + astartes.utils.fast_kennard_stone + +
  • +
  • + astartes.utils.sampler_factory + +
  • +
  • + astartes.utils.user_utils + +
  • +
  • + astartes.utils.warnings + +
  • +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

F

+ + +
+ +

G

+ + + +
+ +

I

+ + + +
+ +

K

+ + + +
+ +

M

+ + + +
+ +

N

+ + + +
+ +

O

+ + +
+ +

P

+ + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + +
+ + + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/index.doctree b/docs/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..24dc41f1e2cfcc33605f76cd5e6bf569973ade7a GIT binary patch literal 4622 zcmds5U5^|`6~I~ zR8{ZJJ|MwE0xJ~=;X;4}Ji}k$7a$ab#4|sJQ`OxwJ!8BHuUMK@*R5N(s_s4a+*|%h z>o==AEB>F^QaR(Bb@|QkrS|+}{4F{juFOJxNZLC}c#fS%F5xcoIvR z*(aFXbo!bnYQHkjiA1`vp0&(Bh|)xAs)E`&(OhIf3OSX*h$r+;5J^fjjf3G?zdY66 zrv;BDeq{jV?@1o~ph$w?+rhp2hX>z0ynhfJ+&wth@BdH~K}52E#3a{&W?Xrb0Zx)9 zRMX@v&>}d)6@r9Mcs9Nh3=17_9VjM>Bo2rU5{k3*BavysGuWVk6ha42wTQH&^l1=t zNh8fq=)Ps0CzkchmB)1I-1Pr;z0a(RyJ_bHLDrV7t06IcqP6638$jYfvC3lw0GLjc z5Tzi*cPk@l`PGe!d_EYGXd>yz>-45+a;S3Rz|_qpRaBl(TbPa}W4FSxKD)tIO)spW zVlish_&XRdk^*g0H+hwJwnrFV3_h*7vwV|bo5wAruxT~^F`PI1p{98R(NMTMSe z^UUXX;~?eQZPTsyvh&;j>E*ZIHCOy5W>x7JDT2RyZd1C9hCd)uzh6dCQ^~Zk4q&kC zLzGbWnWD5<_7~H^NT20kz*T43tl=-6<_V9u29VwKDN@b;+^<9B98<8^{2~s_zpcRh zDvn_=I`TN?jyX^g1U78+6c z*9B2wfBs4V`R7HKds#sK{nZ1){@OTsGYqf6X>XN`dS++EuVRfkPt~(cPPveyKnNEdtt#DY*Sw-7$yDNr zG0deHqx_fML`w@zl9JOa9Z&IvbK51e85Pp?B4K3<1*(?#v_CdoMYRS)po86Z1nfJ~ zk@U3%Y25ypBn7x}#t(yI(*rS3NwknCc)b|CCtA%k$6&482HciSFzi>uLM9k(piYFY zqj9s?uH|aZnKe5j^oyC$v@v;f$!xfG14S#Gj)Y7tB%2CFHxH{eS;6ERrGzHbHO?wL z<(h?cUxgj31y!Sk%S)OI3GSsQ6i&Nr`ivyAVasgODTl8#(S@p&TBa4#VKK&bn~q!@ zo5C(7DI`4vCZg_A;G9jK<%JGu7P%xJqeK^awD+w&#qs^-;$%pr6f$H0Qi76+J`Hz^ zKvr9#(2G`D-ikFhmu8ksJiB*kWyNfkcIRiPSHHP9v9#D+b$0;56oZQr-(+qiBpVlG zOyThulzSPCg}H`aUdT8^LxReJZCn?G76|?S2-k#1cnpN1kC|H5Hk+hC+cOuL%N(HE zh>J82XTXDFy?~>ikr_#x!7VTGuy^5~i*iMaScGVXp>-AHFBA=%D?Lgg9iDK-ONefT zF;}j{<0925J9R=Jxz=$Rg%l{;4xpw|3+rCY+;Csm1TDAgy%1q%Ek?-K&^pbAfatc% zDj+8t1BeMvQI^LN0vp9C*jsU2>S$nAW*E91I{<`}vt>BHI^o zJh0}v)AR>`W{9o;;nDsLK=Zw~?%sz#H{~c=GVdgF^KaMYk*vf)c0%Por+Vb~K-v$O zP7`d_1F0d4V%KbT%}ro34QJ^&yFgezL(a`rb%tl(G-Q0t68!v=K{)8Is}%3n@Y4c$ zt>CC@eq0X2L`0-)bIr|&p?`@G_%h$%W$!|)o)kH1x_c)3Znfe8w6>7&Yy=F{#IWP2 zLKVX$J)S!7CW4gN=pHi@3(TMoj*-G=I0B<+5YEl@2wIbnqR&V|Jn0?1`eScbZyta( z8I`nlZdPe_Vo}{qx1kRj)A5-A5&3Gs)VZHLFWBquwUo0vUXPs=W}_KK zZ+8PtQ&~~4S1EDXTI-b;Xi6N!ycA(iha#CF!wX+o63(=H3l@9zu71(Zf_?u#7LMt! zFWahS@Nxl{M0nEyFlhfGfmYf-N>NWb4=VX{c{zcN2-j>C!~OpNP^$Hh literal 0 HcmV?d00001 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..2255d40d --- /dev/null +++ b/docs/index.html @@ -0,0 +1,184 @@ + + + + + + + astartes documentation — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/modules.doctree b/docs/modules.doctree new file mode 100644 index 0000000000000000000000000000000000000000..14852b17b71f5a2fc263582db149170a93df28a5 GIT binary patch literal 2750 zcmZ8jTWcIQ6n1Ry)w}CUl2S_~P&QKAwevp*L20ld%|fppkJQbHh}88^a{2J0a~wbG~O;=7d)5ao*uw-g_I* z_#kwgaFT6og+8^88VAow2P*r&vt{zVvGXC;adb-xuP*ZAFd%K1d@ppH=&r)P6pFcLR1)CbL6f@HsZLX)QRMsB|(oPGVd&%sDu?YQ(%UwT1n*B@{rS>Y{0Hel< z@4%zZoMD?lHG5wo6aE!|`WnAy_&vw(1%6LLuknKn0g@3_UT0SuIDU)(2ynRgF|sfc zDw95EbAjNH=o$Zs|I9+apv#<pS=U`5NSm^iqQdKT|Omy0|{?eD_4G0+P7$`>HPV+ z7Re4u&RP>2InxzVTe1eVWM>FFdv#5#cu=10ST-HEOye)ZBWI|xk|umeY4pM{TQjZW zw4<^Hq0y-@@yXwVFv+}0JSHt`M=MFq-q5$qIiVJ4$K$rY=0+>WK$y_|gG!H@ts0ac zUWLJefrr#-gCY-dn#xRz5{rY{4T0@zEQig~8;R8zIFrQovQvYcyEL`WtUR4WPCoMwiF$tSghNmfb7jc}Z-dJZ0&15FcNg^^*UHjYU4 zjsdjYFyvIW%T73EO98ALb>6O&I-!%ZnP0%&`JNHcR4`EUp zT?eo_`gD8a-pO#35&*p{2R;%B#W0psEj(Q?z@1~gi#7}o4a>C233?XffSc6#SD~9} zHAjwsL*$?*+I$&#H%zE^nyf`(SAbFD+!rNjSqD@rfdJu*qB0pgtRxlZQ|;HH(lVcG zvMdsxj@Yu)mXXbq6-6>f-U%yeejbusSUQs_ktWLCsvFQ*BP3(N|EjfMblj+s)u;-e zr7t+K%v9~iRI-+%-Uk>osCK;sKaW#Ofi`LZ7D`bF7k@o^9wsF#2|&TLQdtGqC`o1% zv8T=mpL6F*`{Q&9vArm79oOnYo5eJS$4Rpa0Ghc3*~7Z_roa&S&+6j+XRR$6GQI8k-b%p zE(sS4F7X3-_oYs}AK3!;Ecw%;sV#tdSgq?NkvgOGEf7vKP7x0ZUpE_2t{}weYhS`e zy78;o-V6a;1ds?d2M1PD;Uvuo>u2}$M3KlVHLY7QUDnqToWZS;qknG^0%y#@$>R)K z*Mt>RNP@>nnyppX$IbHsWR>%Jrrm`-rrxDXKlJNag60Jkg~|n*!x20%77Viq7ydDV z0<|2TESTE3{L;h@CtK3`82~Y?&D%vcwGdtqkoS_X{^oD^Ya0eh;BHGq_&)MCcb0#J z|F8MThVf>xs?+04pybItEY_0LlPkSC%uPwHhu~4%Vy0zV|4Q}IJz=Xo*s?fSd94ne zY}v0~U}=~?zHh79!EKI-k>R-lTEuXWX(<6La=?|*`=yb8Lh>KtZ(u*(Y3L)otSstX iJ8TEXmiV9*S0y`WUKF6nB2{acr`gtwfpkav*~R}1rAeFs literal 0 HcmV?d00001 diff --git a/docs/modules.html b/docs/modules.html new file mode 100644 index 00000000..9762ff8f --- /dev/null +++ b/docs/modules.html @@ -0,0 +1,189 @@ + + + + + + + astartes — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/docs/modules.rst b/docs/modules.rst new file mode 100644 index 00000000..831c4b4f --- /dev/null +++ b/docs/modules.rst @@ -0,0 +1,8 @@ +astartes +======== + +.. toctree:: + :maxdepth: 4 + + astartes + test diff --git a/docs/objects.inv b/docs/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..e86e41af6fdcb9e2f241d42d8bd0d42dd00c310a GIT binary patch literal 2215 zcmV;Y2w3+cAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkmb97;H zbY*i2BOq2~a&u{KZaN?eBOp|0Wgv28ZDDC{WMy(7Z)PBLXlZjGW@&6?AZc?TV{dJ6 za%FRKWn>_Ab7^j8AbMtESCT|zltk}4C_~j>AYKMRF-oLdCo5am z>xmC6$P=Y-YO@59!@R(V4X9P;4(oR;0Ux=PDUqU>6z_oXrz&C75F{9K-d51YUj`fl zkP+FMK&ybno~GU@o{#_uF1e_iJ|GPxyX+}2iOB<5`WjjtPGzOEZak@7NknCBi%8L{ zq$ntcy045ItyOl03ESn73iN09KKN*Idx%YDt{T?tx< zjAwaJEh>)qtNgz)T%q)+IduO>GcG22gD19}zQ`UgP`(ZwOZJp<6oyQ8o86A$G^k0` zB=M%j=G`cIEYd6pVo)IPi1LhsykyBU1(wRe8nlt3P60x4=UF|KT7y|IMJi`Uff$QD zVhEsDH7JE1MY?41Mkn01$-Uc@$Z}~tkfX32q@jto^5^H8(1SjinkCE}=B=_bl(5S` zBSIicxu68CMihTB51X2GxXB!(bJ!RpDb1T@Q!usKMDch15JVwfydHuoq6p&6w}1XU zPyAA3cwoY%vxem|*^n`K0OC*}ut&HUTyKtj--;d$#cB0T=S!L$H^B zG4uw?kSH0c9+#m?*NX~O<(!6WK;kjKi(!mXPl69)`;xv|3oCr}BS+GG_>z7Y+n4k|NTM_zFfw@>yNI4>o{*x+^-)>=}Auh^zUZ{K-o!xLgP(Vi{^R zG=UvV1Z9UaRPP|w2KHwI+#45960HMx);phoZg#oY67-Tw=yQki1|*it`~u6tt$y2( z1Kk0Zz3~=s7?b)58Og}gIm*`%@wJ|CD8c?VNedmwFyL8sbcB^Y6tNvj#70eJg-r7# z?;x-rxgY2~6v@$g}^ep+t`*X>OwET9Cb!M@O8d*w$*K|FqGC=#5$BF+M~VOz@IUa>n`x}{*Mds zehA2`&N%fE=d$K4N#(|TaPkqT%kUJOzODZr8VY`u%A%c*^FzM)&P6GJ%Y;= zfn=XCITaCyOG-i+LrJwub1^yO1PtsL&6Pm=>|$b&CKe3rXh~A=v)M|$h(rwO*g_~| z+vKpgm>kX!xl0JJj%Rel_6G8cRfzA_W)0;N`)q6ZLkDxWr7uH$G${8h`yz6D2r7pw z<~xve*OANH4sR&?cJZxc;ZE*egI|n&9mhEu03683dU3$pAxT1+-8>1_GQ^qEw94AA z>kZ1aj`0q}b_X)sc8GVMJ(Q^qv#w>HBND8>CYh2Ym!4CO$QV8%eA!lMp4IU$dP}mX z$G0Mne?QUM2%g^NvkK4g3w8xF9UKg{T!XNho_1vzaYqgj{BfV)l)}m}@M_+WJk{aZ z8x>3Kt<2m^IZHxzye1R6+Zd+mXrp&ICyZWgwzay3gSp$%m!V$6;Acs&mTmX$X$7)u zeO*hd+`Y3ELZgOhEsO53)-ydl)jO=te0-~Glg^$jO|ti+`8#9nL|Y_O9NTW(K9sCiUcB%+IZbxU9XqNPgP3hpJQOTtk{By#D&I{eJiP$M){w zuZWBEV@i|g>V4Es*QKLtN(9RuOLdzj`YpOaF9=h0MfibA^mpHHKi%BlwjoT4sr;45 z0R=@jG$~c+xQ?DWUNC7_vOdHWH8(3@@(iDlmSOE4z)Rgz8ht_3rJ|Lq|A4Y6rBf-KqF6-}C{ zvoZPKR2$WSa%w1Y7`Y?cU~J|3foG~ER3}rB4|Ul{&_)q`gQbOcygn6~yDin5>RzDg z*675rM!gGHZJbstUKghmiWl|bVB0u4Jg + + + + + Python Module Index — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Python Module Index

+ +
+ a | + t +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ a
+ astartes +
    + astartes.main +
    + astartes.molecules +
    + astartes.samplers +
    + astartes.samplers.abstract_sampler +
    + astartes.samplers.extrapolation +
    + astartes.samplers.extrapolation.dbscan +
    + astartes.samplers.extrapolation.kmeans +
    + astartes.samplers.extrapolation.optisim +
    + astartes.samplers.extrapolation.scaffold +
    + astartes.samplers.extrapolation.sphere_exclusion +
    + astartes.samplers.extrapolation.time_based +
    + astartes.samplers.interpolation +
    + astartes.samplers.interpolation.kennardstone +
    + astartes.samplers.interpolation.random_split +
    + astartes.samplers.interpolation.spxy +
    + astartes.utils +
    + astartes.utils.array_type_helpers +
    + astartes.utils.exceptions +
    + astartes.utils.fast_kennard_stone +
    + astartes.utils.sampler_factory +
    + astartes.utils.user_utils +
    + astartes.utils.warnings +
 
+ t
+ test +
    + test.functional +
    + test.functional.test_astartes +
    + test.functional.test_molecules +
    + test.regression +
    + test.regression.test_regression +
    + test.unit +
    + test.unit.samplers +
    + test.unit.samplers.extrapolative +
    + test.unit.samplers.extrapolative.test_DBSCAN +
    + test.unit.samplers.extrapolative.test_kmeans +
    + test.unit.samplers.extrapolative.test_optisim +
    + test.unit.samplers.extrapolative.test_Scaffold +
    + test.unit.samplers.extrapolative.test_sphere_exclusion +
    + test.unit.samplers.extrapolative.test_time_based +
    + test.unit.samplers.interpolative +
    + test.unit.samplers.interpolative.test_kennard_stone +
    + test.unit.samplers.interpolative.test_random +
    + test.unit.samplers.interpolative.test_spxy +
    + test.unit.utils +
    + test.unit.utils.test_convert_to_array +
    + test.unit.utils.test_sampler_factory +
    + test.unit.utils.test_utils +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/search.html b/docs/search.html new file mode 100644 index 00000000..5f2ba6be --- /dev/null +++ b/docs/search.html @@ -0,0 +1,131 @@ + + + + + + Search — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + + + +
+ +
+ +
+
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/searchindex.js b/docs/searchindex.js new file mode 100644 index 00000000..9f7d248c --- /dev/null +++ b/docs/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["CONTRIBUTING", "README", "astartes", "astartes.samplers", "astartes.samplers.extrapolation", "astartes.samplers.interpolation", "astartes.utils", "index", "modules", "sklearn_to_astartes", "test", "test.functional", "test.regression", "test.unit", "test.unit.samplers", "test.unit.samplers.extrapolative", "test.unit.samplers.interpolative", "test.unit.utils"], "filenames": ["CONTRIBUTING.rst", "README.rst", "astartes.rst", "astartes.samplers.rst", "astartes.samplers.extrapolation.rst", "astartes.samplers.interpolation.rst", "astartes.utils.rst", "index.rst", "modules.rst", "sklearn_to_astartes.rst", "test.rst", "test.functional.rst", "test.regression.rst", "test.unit.rst", "test.unit.samplers.rst", "test.unit.samplers.extrapolative.rst", "test.unit.samplers.interpolative.rst", "test.unit.utils.rst"], "titles": ["Contributing & Developer Notes", "Online Documentation", "astartes package", "astartes.samplers package", "astartes.samplers.extrapolation package", "astartes.samplers.interpolation package", "astartes.utils package", "astartes documentation", "astartes", "Transitioning from sklearn to astartes", "test package", "test.functional package", "test.regression package", "test.unit package", "test.unit.samplers package", "test.unit.samplers.extrapolative package", "test.unit.samplers.interpolative package", "test.unit.utils package"], "terms": {"pull": 0, "request": [0, 1, 6, 9, 11, 16], "bug": [0, 1], "report": 0, "all": [0, 1, 3, 4, 9, 11, 17], "ar": [0, 1, 4, 9], "welcom": 0, "encourag": [0, 9], "appreci": 0, "pleas": [0, 1], "us": [0, 2, 4, 6, 7, 11, 15, 16, 17], "appropri": [0, 1, 6], "issu": 0, "templat": 0, "when": [0, 1, 6, 9, 11, 16, 17], "make": [0, 1, 9], "help": [0, 1, 9, 11], "maintain": 0, "get": [0, 1, 3, 9], "merg": 0, "quickli": [0, 1], "we": [0, 1, 4, 6, 9], "github": [0, 1, 9], "discuss": [0, 1], "page": [0, 1], "go": [0, 4], "over": [0, 6], "potenti": [0, 1], "add": [0, 4, 6, 9], "feel": 0, "free": 0, "stop": [0, 4], "you": [0, 1, 9], "look": [0, 1, 4, 9], "someth": [0, 15], "have": [0, 1, 4, 9], "an": [0, 1, 4, 6, 7, 11], "idea": 0, "submit": 0, "pr": 0, "mark": 0, "your": [0, 1, 9], "readi": 0, "review": 0, "label": [0, 1, 2, 3, 4, 5, 6, 9, 11, 12, 15], "finish": 0, "chang": [0, 1, 7], "so": [0, 1, 9], "action": 0, "bot": 0, "can": [0, 1, 5, 9, 11], "work": [0, 1, 4, 6, 9], "magic": 0, "To": [0, 1, 4, 9], "astart": [0, 11], "sourc": [0, 4, 5, 7], "code": [0, 5, 6], "start": [0, 4, 7, 11], "fork": 0, "clone": [0, 1], "repositori": [0, 1], "i": [0, 1, 3, 4, 5, 6, 9, 11, 16], "e": [0, 1, 9], "git": [0, 1], "com": [0, 1, 4], "yourusernam": 0, "insid": 0, "run": [0, 1], "pip": [0, 7, 9], "dev": 0, "thi": [0, 1, 4, 5, 6, 9], "set": [0, 1, 2, 4, 5, 6, 9, 11], "up": 0, "requir": [0, 1, 9, 16], "depend": [0, 1], "conform": 0, "our": [0, 1, 9], "format": [0, 1, 6], "standard": [0, 9], "black": 0, "isort": 0, "which": [0, 1, 4, 5, 6, 9, 12], "configur": [0, 1], "automat": 0, "vscode": 0, "like": [0, 1, 4, 5, 9], "warn": [0, 1, 2, 8, 11, 15, 17], "window": [0, 1], "powershel": [0, 1], "maco": [0, 1], "catalina": [0, 1], "newer": [0, 1, 12], "zsh": [0, 1], "doubl": [0, 1], "quot": [0, 1], "around": [0, 1], "charact": [0, 1], "pyproject": 0, "toml": 0, "specifi": [0, 1, 6, 7, 11, 15], "metadata": [0, 6], "also": [0, 1, 4, 6, 9], "__init__": [0, 2, 3, 6], "py": [0, 17], "via": [0, 1], "__version__": 0, "backward": [0, 1], "compat": [0, 1, 9, 11], "python": [0, 1, 9], "3": [0, 1, 4, 7, 12], "7": [0, 1], "c": [0, 1], "import": [0, 1, 7], "print": [0, 6], "from": [0, 1, 2, 4, 5, 7, 15], "importlib": 0, "8": [0, 1, 2, 6, 9], "written": 0, "built": [0, 1], "unittest": 0, "modul": [0, 1, 7, 8], "allow": [0, 1, 9], "without": [0, 6], "pytest": 0, "highli": 0, "recommend": [0, 1], "execut": [0, 1], "simpli": [0, 1, 9], "type": [0, 1, 2, 3, 6, 9, 17], "after": [0, 1, 2, 4, 6], "altern": [0, 1], "v": 0, "more": [0, 1, 4, 6], "output": [0, 5], "On": 0, "everi": [0, 4, 11], "nightli": 0, "basi": 0, "workflow": [0, 1, 9], "inform": [0, 1], "These": [0, 1], "includ": [0, 1, 4, 9, 15], "unit": [0, 1, 5, 8, 10], "regress": [0, 7, 8, 10, 17], "should": [0, 1, 6, 9, 11, 15, 16, 17], "extend": 0, "abstract_sampl": [0, 2, 8], "abstract": [0, 3, 4], "base": [0, 1, 3, 4, 5, 6, 11, 12, 15, 16, 17], "class": [0, 3, 4, 5, 6, 11, 12, 15, 16, 17], "each": [0, 1, 4], "subclass": 0, "overrid": 0, "_sampl": [0, 1], "method": [0, 1, 5, 12], "its": [0, 1, 9], "own": [0, 1], "data": [0, 2, 4, 6, 7, 9, 11, 15], "partit": [0, 1, 4, 5], "option": [0, 1, 2, 3, 6, 9, 11], "_before_sampl": 0, "perform": [0, 1, 6, 9], "ani": [0, 1, 3, 4, 6], "valid": [0, 1, 2, 4, 5, 6, 9, 11], "classifi": 0, "one": [0, 1, 4, 9, 16], "two": [0, 1, 4, 9], "extrapol": [0, 1, 2, 3, 11, 12, 13, 14], "interpol": [0, 1, 2, 3, 11, 12, 13, 14], "cluster": [0, 1, 3, 4], "group": 0, "train": [0, 1, 2, 4, 6, 9, 11], "enforc": 0, "wherea": 0, "provid": [0, 1, 3, 6, 16], "exact": [0, 1, 9], "order": [0, 3, 6], "move": [0, 1, 4, 9], "actual": [0, 1, 9], "mean": [0, 1], "self": [0, 1, 4], "_samples_clust": 0, "attribut": [0, 3, 6, 11, 12, 15, 16, 17], "_samples_idx": 0, "simpl": [0, 1, 17], "passthrough": [0, 1], "anoth": [0, 6], "train_test_split": [0, 1, 2, 8, 9, 11, 15, 16], "origin": [0, 1, 4, 5], "result": [0, 1, 4, 6, 11, 12, 15, 16, 17], "x": [0, 1, 2, 3, 4, 5, 6, 9, 11], "y": [0, 1, 2, 3, 4, 5, 6, 9, 11, 16], "being": [0, 4, 6], "split": [0, 2, 4, 6, 7, 9, 11, 12, 16, 17], "list": [0, 1, 2, 4, 9], "take": [0, 1, 4], "random_split": [0, 2, 3], "basic": 0, "exampl": [0, 7, 9], "ha": [0, 1, 4, 5, 9, 12], "been": [0, 1, 4, 5, 9], "addit": [0, 1, 6, 9], "verifi": [0, 1, 15, 16], "hyperparamet": [0, 1, 2, 6, 9, 11], "properli": [0, 1], "pass": [0, 1, 3, 6, 7, 11], "etc": 0, "For": [0, 1, 9], "histor": 0, "reason": 0, "guid": [0, 1], "who": 0, "would": [0, 4, 6, 11], "below": [0, 1, 3, 9], "consid": [0, 1], "asart": 0, "ultim": [0, 5], "variou": [0, 11, 15, 16], "name": [0, 1, 6], "relev": 0, "link": [0, 1, 5], "": [0, 1, 2, 9], "d": 0, "optim": [0, 1], "priori": 0, "knowledg": 0, "size": [0, 2, 3, 4, 6, 11], "doe": [0, 6], "fit": [0, 4, 6], "framework": [0, 4], "agnost": 0, "question": 0, "fischer": 0, "matrix": [0, 6], "meaning": 0, "context": 0, "exist": [0, 1, 6, 9], "rather": [0, 9], "than": [0, 1, 4, 9, 15], "tune": [0, 9], "ideal": 0, "wikipedia": [0, 1], "articl": [0, 1], "design": [0, 1, 9], "good": 0, "job": 0, "explain": [0, 1], "why": [0, 1], "difficult": [0, 1], "point": [0, 1, 4, 9], "some": [0, 1, 6, 9], "duplex": 0, "know": [0, 1], "befor": 0, "onli": [0, 1], "incompat": [0, 1], "r": [0, 1], "refer": [0, 1, 12], "accept": [0, 1], "arbitrari": [0, 1, 2, 4, 9], "arrai": [0, 1, 2, 3, 6, 9, 11, 16, 17], "number": [0, 3, 15], "return": [0, 1, 2, 3, 4, 6, 9, 11, 17], "except": [0, 1, 2, 8, 9, 11], "scaffold": [0, 1, 2, 3, 6, 15], "If": [0, 1, 4, 9, 11], "input": [0, 1, 9, 11, 15, 17], "turn": 0, "thrill": 0, "interfac": [0, 11], "def": [0, 9], "train_test_split_interfac": 0, "interface_input": 0, "interface_arg": 0, "np": [0, 2, 3, 6, 9], "none": [0, 1, 2, 3, 6, 9], "test_siz": [0, 1, 2, 6, 9], "float": [0, 2, 6, 9], "0": [0, 1, 2, 6, 9], "25": [0, 9], "train_siz": [0, 1, 2, 6, 9], "75": [0, 2, 9], "splitter": 0, "str": [0, 2, 3, 6, 9], "random": [0, 1, 2, 3, 4, 5, 6, 9, 16], "hopt": [0, 1, 2, 3, 6, 9, 11], "dict": [0, 2, 3, 6, 9], "interface_hopt": 0, "arg": 0, "where": [0, 9], "behavior": [0, 1, 9], "call": [0, 1, 3, 6, 9, 15, 17], "possibl": [0, 1, 4, 9, 16], "jupyt": 0, "notebook": [0, 7], "demonstr": 0, "user": [0, 1, 6, 9, 11], "how": [0, 7, 9], "see": [0, 1, 2, 9], "other": [0, 1, 9, 15], "directori": [0, 1], "contact": 0, "jacksonburn": [0, 1], "need": [0, 4, 7, 9], "assist": 0, "mai": [0, 1], "extra": [0, 9], "packag": [0, 1, 7, 8, 9], "same": [0, 1, 2, 4, 6, 9], "wai": [0, 1, 9], "molecul": [0, 4, 6, 8, 9, 11, 15], "workhors": [0, 9], "It": 0, "respons": [0, 1], "instanti": [0, 6, 15, 16], "while": [0, 1, 9], "keep": [0, 1], "ey": 0, "under": [0, 1], "hood": 0, "just": [0, 4, 9], "val_siz": [0, 2, 6, 9], "out": [0, 1, 9], "inlin": 0, "document": 0, "main": [0, 1, 8], "priorit": 0, "1": [0, 1, 2, 4, 6, 7], "reproduc": [0, 7], "2": [0, 1, 4, 7, 12], "flexibl": 0, "produc": [0, 1, 9], "across": [0, 1], "platform": [0, 1], "thorough": 0, "continu": [0, 1], "few": [0, 9], "loosest": 0, "integr": [0, 1], "tool": [0, 1], "easili": 0, "introduc": [0, 1, 4], "lot": [0, 6], "specif": [0, 7], "shuffl": [0, 1, 3, 11], "extras_requir": 0, "avoid": 0, "weigh": 0, "down": [0, 11], "modern": 0, "achiev": [0, 1], "tightli": 0, "well": [0, 1, 4, 12], "follow": [0, 1], "dry": 0, "don": 0, "t": [0, 11], "repeat": [0, 4], "yourself": 0, "principl": 0, "duplic": 0, "decreas": 0, "burden": 0, "perfect": [0, 1], "coverag": 0, "consist": [0, 1], "style": 0, "comment": 0, "critic": [0, 1], "time": [0, 1, 9], "write": 0, "line": [0, 9], "correspond": [0, 1, 2, 5, 6], "paper": [0, 1, 4, 5], "store": [0, 1], "separ": [0, 1, 9], "find": 0, "md": [0, 1], "aptli": 0, "push": 0, "updat": 0, "tar": 1, "tee": 1, "raw": 1, "html": [1, 4, 9], "m2r": 1, "p": 1, "align": 1, "center": [1, 4], "img": 1, "alt": 1, "astarteslogo": 1, "src": 1, "http": [1, 4, 9], "githubusercont": 1, "astartes_logo": 1, "png": 1, "statu": 1, "badg": 1, "usag": 1, "releas": 1, "nice": 1, "render": 1, "version": [1, 7], "readm": [1, 9], "along": 1, "tutori": 1, "sklearn": [1, 6, 7, 12], "read": 1, "within": [1, 4, 17], "virtual": 1, "environ": [1, 9], "either": [1, 6], "venv": 1, "simplifi": 1, "manag": 1, "9": 1, "10": [1, 4, 5], "11": [1, 4], "support": [1, 6, 9, 17], "text": 1, "avail": [1, 9], "pypi": 1, "featur": [1, 2, 4, 6, 7, 11], "fewer": 1, "readili": 1, "forg": 1, "command": 1, "aimsim": [1, 2, 9], "download": 1, "backend": 1, "molecular": [1, 2, 4, 9, 11], "section": 1, "machin": [1, 9], "learn": [1, 9], "spark": 1, "explos": 1, "progress": 1, "kinet": 1, "materi": 1, "scienc": 1, "mani": [1, 6, 9], "field": 1, "research": 1, "driven": 1, "acceler": 1, "step": [1, 4, 7, 11], "tradit": 1, "error": [1, 6, 11, 17], "toler": 1, "facilit": 1, "adopt": 1, "task": [1, 17], "select": [1, 4, 6], "held": [1, 9], "measur": [1, 4], "unseen": 1, "both": 1, "futur": 1, "address": 1, "function": [1, 4, 6, 7, 8, 9, 10, 15, 16, 17], "technic": 1, "detail": 1, "companion": 1, "demo": 1, "fast": 1, "food": 1, "menu": 1, "publish": 1, "state": 1, "softwar": 1, "engin": 1, "confer": 1, "gener": [1, 9, 17], "involv": 1, "discoveri": 1, "infer": 1, "There": [1, 9], "cheminformat": [1, 4, 9], "numer": 1, "drop": 1, "replac": 1, "switch": [1, 9], "model_select": [1, 9], "iter": 1, "object": [1, 2, 6, 9, 11, 15], "convert": [1, 4, 6], "numpi": [1, 2, 6, 9], "intern": 1, "oper": 1, "panda": [1, 2, 6], "datafram": [1, 2, 6, 17], "seri": [1, 2, 6, 17], "cast": [1, 6, 17], "back": 1, "index": [1, 7], "column": [1, 6], "The": [1, 2, 4, 5, 6, 7, 9], "handl": [1, 17], "convers": [1, 4], "explicitli": 1, "behind": [1, 9], "scene": [1, 9], "lead": 1, "unexpect": 1, "By": [1, 9], "default": [1, 2, 3, 6, 9], "randomli": 1, "addition": 1, "varieti": 1, "approach": 1, "sampler": [1, 2, 6, 7, 8, 10, 11, 13, 17], "argument": [1, 7], "tabl": [1, 6], "complet": [1, 9], "dataset": [1, 2, 4, 6], "load_diabet": 1, "return_x_i": 1, "true": [1, 2, 9], "x_train": [1, 9], "x_test": [1, 9], "y_train": [1, 9], "y_test": [1, 9], "prefer": 1, "kennard_ston": [1, 9, 16], "valueerror": [1, 15], "too": 1, "valu": [1, 2, 3, 4, 6, 9, 11], "unpack": 1, "split_comparison": 1, "googl": 1, "colab": 1, "blob": 1, "ipynb": 1, "_": [1, 9], "full": [1, 4], "explan": 1, "That": [1, 9], "next": 1, "try": [1, 9, 11], "browser": 1, "click": 1, "taken": 1, "live": 1, "interact": 1, "local": 1, "navig": 1, "open": [1, 4], "editor": 1, "do": [1, 6, 9, 17], "cell": 1, "prefix": 1, "captur": 1, "thei": 1, "present": [1, 3], "rigor": 1, "ml": 1, "dure": [1, 9], "never": [1, 4], "unlik": 1, "accur": 1, "With": [1, 9], "three": [1, 9], "x_val": [1, 9], "sphere_exclus": [1, 2, 3, 9, 15], "now": [1, 9], "visual": 1, "differ": [1, 5, 11], "distribut": 1, "aid": 1, "analyz": 1, "generate_regression_results_dict": [1, 2, 6], "techniqu": 1, "nest": [1, 6], "dictionari": [1, 4, 6, 17], "metric": [1, 4, 6], "score": 1, "displai": 1, "neatli": 1, "print_result": [1, 6], "svm": 1, "linearsvr": 1, "util": [1, 2, 8, 10, 13], "grrd": 1, "sklearn_model": [1, 6], "results_dict": 1, "val": [1, 2, 6], "mae": [1, 6], "41522": 1, "13435": 1, "17091": 1, "rmse": [1, 6], "03062": 1, "73721": 1, "40041": 1, "r2": [1, 6], "90745": 1, "80787": 1, "78412": 1, "additional_metr": [1, 6], "map": [1, 4, 6, 15], "string": [1, 2, 3, 4, 6, 9], "itself": 1, "mean_absolute_percentage_error": 1, "add_met": 1, "mape": 1, "docstr": [1, 11], "whose": 1, "distance_metr": 1, "effect": 1, "co": 1, "opt": 1, "encod": [1, 9], "choic": 1, "jaccard_scor": 1, "distanc": [1, 4, 5, 6], "did": 1, "incept": 1, "though": [1, 4, 9], "adapt": [1, 4], "interest": [1, 9], "ad": [1, 4, 7], "In": [1, 9], "kennard": [1, 6, 9, 16], "stone": [1, 6, 9, 16], "retriev": 1, "kennardston": [1, 2, 3, 16], "4": [1, 4, 7], "5": [1, 4, 7], "6": [1, 4], "first_2_sampl": 1, "get_sample_idx": [1, 2, 3], "constructor": 1, "greedili": 1, "get_sampler_idx": 1, "get_cluster_idx": 1, "respect": 1, "implementaiton": 1, "motiv": 1, "comprehens": 1, "walkthrough": 1, "freeli": 1, "host": 1, "here": [1, 4], "public": 1, "wherev": 1, "lock": 1, "paywal": 1, "denot": 1, "small_blue_diamond": 1, "instead": [1, 2, 4, 6, 9], "suggest": [1, 4, 11], "absolut": 1, "attempt": [1, 6], "bypass": 1, "much": 1, "done": 1, "between": [1, 4], "similar": [1, 4], "divid": 1, "sphere": [1, 4, 9], "exclus": [1, 4, 9], "tropsha": 1, "et": [1, 4], "al": [1, 4], "optisim": [1, 2, 3, 15], "appli": 1, "chemoinformat": 1, "opportun": 1, "incorpor": 1, "dbscan": [1, 2, 3, 15], "broad": 1, "categori": 1, "former": 1, "forc": 1, "predict": 1, "creat": [1, 4], "challeng": 1, "current": [1, 9], "understand": 1, "random_st": [1, 2, 3, 6, 9], "defin": 1, "keyword": [1, 7], "even": 1, "overwritten": 1, "direct": 1, "euclidian": [1, 4], "describ": [1, 4, 5], "joint": 1, "spxy": [1, 2, 3, 16], "saldhana": 1, "extens": 1, "mahalanobi": 1, "mdk": 1, "deriv": 1, "saptoro": 1, "include_chir": [1, 4], "bemi": [1, 4, 6], "murcko": [1, 4, 6], "rdkit": [1, 2, 4, 6, 9, 11], "smile": [1, 2, 4, 9, 15], "distance_cutoff": [1, 9], "custom": 1, "variat": 1, "vector": [1, 2, 4, 6, 9], "time_bas": [1, 2, 3, 15], "chen": 1, "sheridan": 1, "feinberg": 1, "strubl": 1, "date": [1, 15], "datetim": [1, 15], "optimiz": [1, 4], "k": [1, 4], "dissimilar": [1, 4], "n_cluster": [1, 9], "max_subsample_s": 1, "kmean": [1, 2, 3, 9, 12, 15], "n_init": 1, "scikit": 1, "org": [1, 4], "stabl": 1, "densiti": 1, "spatial": [1, 4], "nois": 1, "ep": 1, "min_sampl": 1, "leaf_siz": 1, "minimum": 1, "mtsd": 1, "upcom": 1, "v1": [1, 12], "restrict": 1, "boltzmann": 1, "rbm": 1, "kohonen": 1, "organ": 1, "som": 1, "new": [1, 3, 7], "enorm": 1, "chemistri": 1, "relat": 1, "due": 1, "high": 1, "dimension": 1, "space": 1, "accuraci": 1, "process": [1, 4], "pre": [1, 4], "common": 1, "train_test_split_molecul": [1, 2, 8, 9], "ident": [1, 9], "control": [1, 9], "fingerprint": [1, 2, 11], "daylight_fingerprint": [1, 11], "fprints_hopt": [1, 2], "minpath": 1, "maxpath": 1, "fpsize": 1, "200": 1, "bitsperhash": 1, "useh": 1, "tgtdensiti": 1, "minsiz": 1, "64": 1, "42": [1, 2, 9], "brief": 1, "scheme": [1, 7, 9], "found": [1, 5], "most": [1, 4, 9], "shown": 1, "abov": [1, 2, 5], "aim": 1, "alwai": 1, "end": 1, "seed": [1, 2, 6], "debian": 1, "ubuntu": 1, "intel": 1, "mac": 1, "through": [1, 9, 11], "inevit": 1, "extern": 1, "catch": 1, "initi": [1, 4, 6], "affect": 1, "given": [1, 4, 9], "abil": [1, 11, 15], "m1": 1, "manual": 1, "reproducbl": 1, "case": [1, 4], "occasion": 1, "appl": 1, "silicon": 1, "still": [1, 9], "appar": 1, "citat": 1, "button": 1, "bibtex": 1, "burns_jackson_2023_8147205": 1, "author": [1, 9], "burn": 1, "jackson": 1, "spiekermann": 1, "kevin": 1, "bhattacharje": 1, "himaghna": 1, "vlacho": 1, "dionisio": 1, "green": 1, "william": 1, "titl": 1, "month": 1, "year": 1, "2023": 1, "zenodo": 1, "doi": [1, 4, 5], "5281": 1, "8147205": 1, "url": 1, "instruct": 1, "guidanc": 1, "abstractsampl": [2, 3, 4, 5], "get_clust": [2, 3, 6], "get_config": [2, 3], "get_sorted_cluster_count": [2, 3], "array_type_help": [2, 8], "convert_to_arrai": [2, 6], "panda_handla": [2, 6], "return_help": [2, 6], "invalidconfigurationerror": [2, 6], "invalidmodeltypeerror": [2, 6], "moleculesnotinstallederror": [2, 6], "samplernotimplementederror": [2, 6], "uncastableinputerror": [2, 6], "fast_kennard_ston": [2, 8], "sampler_factori": [2, 8], "samplerfactori": [2, 6, 17], "get_sampl": [2, 6], "user_util": [2, 8], "display_results_as_t": [2, 6], "conversionwarn": [2, 6], "imperfectsplittingwarn": [2, 6], "nomatchingscaffold": [2, 6], "normalizationwarn": [2, 6], "int": [2, 6], "return_indic": [2, 6], "bool": [2, 6, 9], "fals": [2, 4, 6, 9], "determinist": 2, "paramet": [2, 3, 6], "target": [2, 6, 7], "must": [2, 6], "fraction": [2, 6], "test": [2, 4, 5, 6, 7, 8, 9], "implemented_int": 2, "extrapolation_sampl": 2, "throughout": [2, 6], "indic": [2, 4, 6, 9, 11], "train_val_test_split": [2, 7, 8, 11], "pd": [2, 6], "morgan_fingerprint": 2, "repres": 2, "reaction": 2, "train_val_test_split_molecul": [2, 8, 11], "get_dist": [3, 4], "move_item": [3, 4], "rchoos": [3, 4], "generate_bemis_murcko_scaffold": [3, 4], "scaffold_to_smil": [3, 4], "str_to_mol": [3, 4], "sphereexclus": [3, 4], "timebas": [3, 4, 12, 15], "sampl": [3, 4, 5, 7, 9], "config": [3, 4, 5], "abc": 3, "copi": [3, 6], "getter": 3, "kei": [3, 6], "_config": 3, "els": 3, "n_sampl": 3, "idx": 3, "max_shufflable_s": 3, "contain": [3, 4, 17], "cluster_id": 3, "member": [3, 4], "sort": 3, "ascend": 3, "accord": [3, 9], "algorithm": [4, 5, 6, 7], "clark": 4, "pub": 4, "ac": 4, "1021": 4, "ci970282v": 4, "treat": 4, "remain": 4, "candid": 4, "empti": [4, 6], "recycl": 4, "bin": 4, "subsampl": 4, "remov": 4, "greater": 4, "cutoff": 4, "otherwis": [4, 6], "until": [4, 9], "condit": 4, "met": 4, "reach": 4, "determin": 4, "maximum": 4, "exhaust": 4, "b": 4, "quit": 4, "alreadi": [4, 9], "identifi": 4, "pick": 4, "rel": [4, 12], "suffici": 4, "As": 4, "assign": 4, "element": 4, "belong": 4, "implement": [4, 5, 6, 9], "scipi": 4, "cdist": 4, "seem": 4, "might": 4, "infinit": 4, "loop": [4, 6], "fill": [4, 6], "cannot": [4, 6, 15], "unless": 4, "empyt": 4, "somehow": 4, "fix": 4, "partial": 4, "sinc": 4, "probabl": 4, "reject": 4, "check": [4, 7, 9, 11, 12], "exit": 4, "j": [4, 5], "calcul": [4, 15], "pdist": 4, "item": [4, 6], "source_set": 4, "destintation_set": 4, "destination_set": 4, "choos": 4, "_rng": 4, "g": 4, "w": 4, "m": 4, "A": [4, 5], "properti": 4, "known": [4, 7], "drug": 4, "med": 4, "chem": 4, "1996": 4, "39": 4, "2887": 4, "2893": 4, "landrum": 4, "2006": 4, "www": 4, "goal": 4, "share": 4, "later": [4, 9, 11, 12, 15, 16], "mol": 4, "comput": 4, "param": 4, "whether": [4, 6], "chiral": [4, 15], "uniqu": 4, "inchi": [4, 15], "re": [4, 16, 17], "draw": 4, "blog": 4, "post": 4, "blogspot": 4, "2020": 4, "daylight": 4, "whitepap": 4, "clusteringwhitepap": 4, "pdf": 4, "But": [4, 9], "tanimoto": 4, "domain": [4, 7], "zero": [4, 11], "enabl": 4, "join": 5, "saldanha": 5, "cowork": 5, "calibr": 5, "subset": 5, "1016": 5, "talanta": 5, "2005": 5, "03": 5, "025": 5, "against": 5, "reflect": 5, "expect": [5, 11], "implemen": 5, "break": 5, "ti": 5, "compar": 5, "minor": 5, "inconsequenti": 5, "obj": 6, "human": 6, "readabl": 6, "helper": 6, "deal": 6, "sampler_inst": 6, "train_idx": 6, "val_idx": 6, "test_idx": 6, "output_is_panda": 6, "conveni": [6, 11, 12, 15, 16], "instanc": 6, "about": 6, "note": [6, 7, 11], "past": 6, "could": [6, 9], "prone": 6, "long": 6, "prettiest": 6, "definit": 6, "what": 6, "want": [6, 9], "messag": 6, "runtimeerror": 6, "model": [6, 7, 9], "invalid": 6, "instal": [6, 7], "non": 6, "ks_distanc": 6, "ndarrai": 6, "lowercas": 6, "desir": 6, "rais": [6, 11, 15, 17], "yet": 6, "error_dict": 6, "neat": 6, "tabul": 6, "samplers_hopt": 6, "func": 6, "those": 6, "runtimewarn": 6, "match": 6, "onlin": 7, "conda": [7, 9], "statement": 7, "audienc": 7, "quick": 7, "withhold": 7, "evalu": 7, "impact": 7, "categor": 7, "access": 7, "directli": [7, 9, 15, 16], "theori": 7, "applic": 7, "ration": 7, "limit": 7, "cite": 7, "contribut": 7, "develop": 7, "philosophi": 7, "joss": 7, "branch": 7, "transit": 7, "subpackag": 8, "submodul": [8, 10, 13, 14], "content": 8, "test_astart": [8, 10], "test_molecul": [8, 10], "test_regress": [8, 10], "reli": 9, "becaus": 9, "part": 9, "vlachosgroup": 9, "io": 9, "pars": 9, "graph": [9, 11], "singl": 9, "place": 9, "represent": 9, "chemic": 9, "invit": 9, "explor": 9, "descriptor": [9, 11], "made": 9, "first": 9, "script": 9, "were": 9, "becom": 9, "interoper": 9, "real": 9, "them": [9, 17], "labels_train": 9, "labels_test": 9, "tunabl": 9, "fine": 9, "15": 9, "circumst": 9, "larg": 9, "memori": 9, "intens": 9, "themselv": 9, "manipul": 9, "indices_train": 9, "indices_test": 9, "benefici": 9, "usual": 9, "y_val": 9, "truli": 9, "veri": 9, "final": 9, "sens": 9, "better": 9, "wors": 9, "believ": 9, "event": [9, 11], "mathemat": [9, 16], "dimens": 9, "50": 9, "101": 9, "runtim": 9, "occur": 9, "quietli": 9, "felt": 9, "prudent": 9, "enter": 9, "normal": 9, "hopefulli": 9, "prevent": 9, "head": 9, "scratch": 9, "hour": 9, "debug": 9, "setupclass": [10, 11, 12, 13, 14, 15, 16, 17], "test_close_mispelling_sampl": [10, 11], "test_inconsistent_input_length": [10, 11], "test_insufficient_dataset_test": [10, 11], "test_insufficient_dataset_train": [10, 11], "test_insufficient_dataset_v": [10, 11], "test_not_implemented_sampl": [10, 11], "test_return_indic": [10, 11], "test_return_indices_with_valid": [10, 11], "test_split_valid": [10, 11], "test_train_test_split": [10, 11, 13, 17], "test_train_val_test_split": [10, 11], "test_train_val_test_split_extrpolation_shuffl": [10, 11], "test_fingerprint": [10, 11], "test_fprint_hopt": [10, 11], "test_maximum_cal": [10, 11], "test_molecules_with_rdkit": [10, 11], "test_molecules_with_troublesome_smil": [10, 11], "test_sampler_hopt": [10, 11], "test_validation_split_molecul": [10, 11], "test_extrapolation_regress": [10, 12], "test_interpolation_regress": [10, 12], "test_kmeans_regression_sklearn_v12": [10, 12], "test_kmeans_regression_sklearn_v13": [10, 12], "test_timebased_regress": [10, 12], "test_convert_to_arrai": [10, 13], "test_sampler_factori": [10, 13], "test_util": [10, 13], "methodnam": [11, 12, 15, 16, 17], "runtest": [11, 12, 15, 16, 17], "testcas": [11, 12, 15, 16, 17], "classmethod": [11, 12, 15, 16, 17], "typo": 11, "length": 11, "round": 11, "funat": 11, "imperfect": 11, "inhomogen": 11, "variabl": 11, "save": [12, 16, 17], "static": 12, "earlier": 12, "test_dbscan": [13, 14], "test_scaffold": [13, 14], "test_kmean": [13, 14], "test_optisim": [13, 14], "test_sphere_exclus": [13, 14], "test_time_bas": [13, 14], "test_kennard_ston": [13, 14], "test_random": [13, 14], "test_spxi": [13, 14], "test_bad_type_cast": [13, 17], "test_convertable_input": [13, 17], "test_panda_handla": [13, 17], "test_unconvertable_input": [13, 17], "test_generate_regression_results_dict": [13, 17], "test_dbscan_sampl": [14, 15], "test_include_chir": [14, 15], "test_incorrect_input": [14, 15], "test_mol_from_inchi": [14, 15], "test_no_scaffold_found_warn": [14, 15], "test_remove_atom_map": [14, 15], "test_scaffold_sampl": [14, 15], "test_kmeans_sampling_v12": [14, 15], "test_kmeans_sampling_v13": [14, 15], "test_optisim_sampl": [14, 15], "test_sphereexclus": [14, 15], "test_sphereexclusion_sampl": [14, 15], "test_mising_label": [14, 15], "test_time_based_d": [14, 15], "test_time_based_datetim": [14, 15], "test_time_based_sampl": [14, 15], "test_kennard_stone_sampl": [14, 16], "test_kennard_stone_sample_no_warn": [14, 16], "test_random_sampl": [14, 16], "test_random_sample_no_warn": [14, 16], "test_missing_i": [14, 16], "test_spxy_sampl": [14, 16], "typeerror": 15, "load": 15, "atom": 15, "neither": 15, "nor": 15, "Not": 15, "tt": 16, "complain": 16, "fail": 17, "factori": 17}, "objects": {"": [[2, 0, 0, "-", "astartes"], [10, 0, 0, "-", "test"]], "astartes": [[2, 0, 0, "-", "main"], [2, 0, 0, "-", "molecules"], [3, 0, 0, "-", "samplers"], [6, 0, 0, "-", "utils"]], "astartes.main": [[2, 1, 1, "", "train_test_split"], [2, 1, 1, "", "train_val_test_split"]], "astartes.molecules": [[2, 1, 1, "", "train_test_split_molecules"], [2, 1, 1, "", "train_val_test_split_molecules"]], "astartes.samplers": [[3, 0, 0, "-", "abstract_sampler"], [4, 0, 0, "-", "extrapolation"], [5, 0, 0, "-", "interpolation"]], "astartes.samplers.abstract_sampler": [[3, 2, 1, "", "AbstractSampler"]], "astartes.samplers.abstract_sampler.AbstractSampler": [[3, 3, 1, "", "__init__"], [3, 3, 1, "", "get_clusters"], [3, 3, 1, "", "get_config"], [3, 3, 1, "", "get_sample_idxs"], [3, 3, 1, "", "get_sorted_cluster_counter"]], "astartes.samplers.extrapolation": [[4, 0, 0, "-", "dbscan"], [4, 0, 0, "-", "kmeans"], [4, 0, 0, "-", "optisim"], [4, 0, 0, "-", "scaffold"], [4, 0, 0, "-", "sphere_exclusion"], [4, 0, 0, "-", "time_based"]], "astartes.samplers.extrapolation.dbscan": [[4, 2, 1, "", "DBSCAN"]], "astartes.samplers.extrapolation.kmeans": [[4, 2, 1, "", "KMeans"]], "astartes.samplers.extrapolation.optisim": [[4, 2, 1, "", "OptiSim"]], "astartes.samplers.extrapolation.optisim.OptiSim": [[4, 3, 1, "", "get_dist"], [4, 3, 1, "", "move_item"], [4, 3, 1, "", "rchoose"]], "astartes.samplers.extrapolation.scaffold": [[4, 2, 1, "", "Scaffold"]], "astartes.samplers.extrapolation.scaffold.Scaffold": [[4, 3, 1, "", "generate_bemis_murcko_scaffold"], [4, 3, 1, "", "scaffold_to_smiles"], [4, 3, 1, "", "str_to_mol"]], "astartes.samplers.extrapolation.sphere_exclusion": [[4, 2, 1, "", "SphereExclusion"]], "astartes.samplers.extrapolation.time_based": [[4, 2, 1, "", "TimeBased"]], "astartes.samplers.interpolation": [[5, 0, 0, "-", "kennardstone"], [5, 0, 0, "-", "random_split"], [5, 0, 0, "-", "spxy"]], "astartes.samplers.interpolation.kennardstone": [[5, 2, 1, "", "KennardStone"]], "astartes.samplers.interpolation.random_split": [[5, 2, 1, "", "Random"]], "astartes.samplers.interpolation.spxy": [[5, 2, 1, "", "SPXY"]], "astartes.utils": [[6, 0, 0, "-", "array_type_helpers"], [6, 0, 0, "-", "exceptions"], [6, 0, 0, "-", "fast_kennard_stone"], [6, 1, 1, "", "generate_regression_results_dict"], [6, 0, 0, "-", "sampler_factory"], [6, 0, 0, "-", "user_utils"], [6, 0, 0, "-", "warnings"]], "astartes.utils.array_type_helpers": [[6, 1, 1, "", "convert_to_array"], [6, 1, 1, "", "panda_handla"], [6, 1, 1, "", "return_helper"]], "astartes.utils.exceptions": [[6, 4, 1, "", "InvalidConfigurationError"], [6, 4, 1, "", "InvalidModelTypeError"], [6, 4, 1, "", "MoleculesNotInstalledError"], [6, 4, 1, "", "SamplerNotImplementedError"], [6, 4, 1, "", "UncastableInputError"]], "astartes.utils.exceptions.InvalidConfigurationError": [[6, 3, 1, "", "__init__"]], "astartes.utils.exceptions.InvalidModelTypeError": [[6, 3, 1, "", "__init__"]], "astartes.utils.exceptions.MoleculesNotInstalledError": [[6, 3, 1, "", "__init__"]], "astartes.utils.exceptions.SamplerNotImplementedError": [[6, 3, 1, "", "__init__"]], "astartes.utils.exceptions.UncastableInputError": [[6, 3, 1, "", "__init__"]], "astartes.utils.fast_kennard_stone": [[6, 1, 1, "", "fast_kennard_stone"]], "astartes.utils.sampler_factory": [[6, 2, 1, "", "SamplerFactory"]], "astartes.utils.sampler_factory.SamplerFactory": [[6, 3, 1, "", "__init__"], [6, 3, 1, "", "get_sampler"]], "astartes.utils.user_utils": [[6, 1, 1, "", "display_results_as_table"], [6, 1, 1, "", "generate_regression_results_dict"]], "astartes.utils.warnings": [[6, 4, 1, "", "ConversionWarning"], [6, 4, 1, "", "ImperfectSplittingWarning"], [6, 4, 1, "", "NoMatchingScaffold"], [6, 4, 1, "", "NormalizationWarning"]], "astartes.utils.warnings.ConversionWarning": [[6, 3, 1, "", "__init__"]], "astartes.utils.warnings.ImperfectSplittingWarning": [[6, 3, 1, "", "__init__"]], "astartes.utils.warnings.NoMatchingScaffold": [[6, 3, 1, "", "__init__"]], "astartes.utils.warnings.NormalizationWarning": [[6, 3, 1, "", "__init__"]], "test": [[11, 0, 0, "-", "functional"], [12, 0, 0, "-", "regression"], [13, 0, 0, "-", "unit"]], "test.functional": [[11, 0, 0, "-", "test_astartes"], [11, 0, 0, "-", "test_molecules"]], "test.functional.test_astartes": [[11, 2, 1, "", "Test_astartes"]], "test.functional.test_astartes.Test_astartes": [[11, 3, 1, "", "setUpClass"], [11, 3, 1, "", "test_close_mispelling_sampler"], [11, 3, 1, "", "test_inconsistent_input_lengths"], [11, 3, 1, "", "test_insufficient_dataset_test"], [11, 3, 1, "", "test_insufficient_dataset_train"], [11, 3, 1, "", "test_insufficient_dataset_val"], [11, 3, 1, "", "test_not_implemented_sampler"], [11, 3, 1, "", "test_return_indices"], [11, 3, 1, "", "test_return_indices_with_validation"], [11, 3, 1, "", "test_split_validation"], [11, 3, 1, "", "test_train_test_split"], [11, 3, 1, "", "test_train_val_test_split"], [11, 3, 1, "", "test_train_val_test_split_extrpolation_shuffling"]], "test.functional.test_molecules": [[11, 2, 1, "", "Test_molecules"]], "test.functional.test_molecules.Test_molecules": [[11, 3, 1, "", "setUpClass"], [11, 3, 1, "", "test_fingerprints"], [11, 3, 1, "", "test_fprint_hopts"], [11, 3, 1, "", "test_maximum_call"], [11, 3, 1, "", "test_molecules"], [11, 3, 1, "", "test_molecules_with_rdkit"], [11, 3, 1, "", "test_molecules_with_troublesome_smiles"], [11, 3, 1, "", "test_sampler_hopts"], [11, 3, 1, "", "test_validation_split_molecules"]], "test.regression": [[12, 0, 0, "-", "test_regression"]], "test.regression.test_regression": [[12, 2, 1, "", "Test_regression"]], "test.regression.test_regression.Test_regression": [[12, 3, 1, "", "setUpClass"], [12, 3, 1, "", "test_extrapolation_regression"], [12, 3, 1, "", "test_interpolation_regression"], [12, 3, 1, "", "test_kmeans_regression_sklearn_v12"], [12, 3, 1, "", "test_kmeans_regression_sklearn_v13"], [12, 3, 1, "", "test_timebased_regression"]], "test.unit": [[14, 0, 0, "-", "samplers"], [17, 0, 0, "-", "utils"]], "test.unit.samplers": [[15, 0, 0, "-", "extrapolative"], [16, 0, 0, "-", "interpolative"]], "test.unit.samplers.extrapolative": [[15, 0, 0, "-", "test_DBSCAN"], [15, 0, 0, "-", "test_Scaffold"], [15, 0, 0, "-", "test_kmeans"], [15, 0, 0, "-", "test_optisim"], [15, 0, 0, "-", "test_sphere_exclusion"], [15, 0, 0, "-", "test_time_based"]], "test.unit.samplers.extrapolative.test_DBSCAN": [[15, 2, 1, "", "Test_DBSCAN"]], "test.unit.samplers.extrapolative.test_DBSCAN.Test_DBSCAN": [[15, 3, 1, "", "setUpClass"], [15, 3, 1, "", "test_dbscan"], [15, 3, 1, "", "test_dbscan_sampling"]], "test.unit.samplers.extrapolative.test_Scaffold": [[15, 2, 1, "", "Test_scaffold"]], "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold": [[15, 3, 1, "", "setUpClass"], [15, 3, 1, "", "test_include_chirality"], [15, 3, 1, "", "test_incorrect_input"], [15, 3, 1, "", "test_mol_from_inchi"], [15, 3, 1, "", "test_no_scaffold_found_warning"], [15, 3, 1, "", "test_remove_atom_map"], [15, 3, 1, "", "test_scaffold"], [15, 3, 1, "", "test_scaffold_sampling"]], "test.unit.samplers.extrapolative.test_kmeans": [[15, 2, 1, "", "Test_kmeans"]], "test.unit.samplers.extrapolative.test_kmeans.Test_kmeans": [[15, 3, 1, "", "setUpClass"], [15, 3, 1, "", "test_kmeans"], [15, 3, 1, "", "test_kmeans_sampling_v12"], [15, 3, 1, "", "test_kmeans_sampling_v13"]], "test.unit.samplers.extrapolative.test_optisim": [[15, 2, 1, "", "Test_optisim"]], "test.unit.samplers.extrapolative.test_optisim.Test_optisim": [[15, 3, 1, "", "setUpClass"], [15, 3, 1, "", "test_optisim"], [15, 3, 1, "", "test_optisim_sampling"]], "test.unit.samplers.extrapolative.test_sphere_exclusion": [[15, 2, 1, "", "Test_sphere_exclusion"]], "test.unit.samplers.extrapolative.test_sphere_exclusion.Test_sphere_exclusion": [[15, 3, 1, "", "setUpClass"], [15, 3, 1, "", "test_sphereexclusion"], [15, 3, 1, "", "test_sphereexclusion_sampling"]], "test.unit.samplers.extrapolative.test_time_based": [[15, 2, 1, "", "Test_time_based"]], "test.unit.samplers.extrapolative.test_time_based.Test_time_based": [[15, 3, 1, "", "setUpClass"], [15, 3, 1, "", "test_incorrect_input"], [15, 3, 1, "", "test_mising_labels"], [15, 3, 1, "", "test_time_based_date"], [15, 3, 1, "", "test_time_based_datetime"], [15, 3, 1, "", "test_time_based_sampling"]], "test.unit.samplers.interpolative": [[16, 0, 0, "-", "test_kennard_stone"], [16, 0, 0, "-", "test_random"], [16, 0, 0, "-", "test_spxy"]], "test.unit.samplers.interpolative.test_kennard_stone": [[16, 2, 1, "", "Test_kennard_stone"]], "test.unit.samplers.interpolative.test_kennard_stone.Test_kennard_stone": [[16, 3, 1, "", "setUpClass"], [16, 3, 1, "", "test_kennard_stone"], [16, 3, 1, "", "test_kennard_stone_sample"], [16, 3, 1, "", "test_kennard_stone_sample_no_warning"]], "test.unit.samplers.interpolative.test_random": [[16, 2, 1, "", "Test_random"]], "test.unit.samplers.interpolative.test_random.Test_random": [[16, 3, 1, "", "setUpClass"], [16, 3, 1, "", "test_random"], [16, 3, 1, "", "test_random_sample"], [16, 3, 1, "", "test_random_sample_no_warning"]], "test.unit.samplers.interpolative.test_spxy": [[16, 2, 1, "", "Test_SPXY"]], "test.unit.samplers.interpolative.test_spxy.Test_SPXY": [[16, 3, 1, "", "setUpClass"], [16, 3, 1, "", "test_missing_y"], [16, 3, 1, "", "test_spxy"], [16, 3, 1, "", "test_spxy_sampling"]], "test.unit.utils": [[17, 0, 0, "-", "test_convert_to_array"], [17, 0, 0, "-", "test_sampler_factory"], [17, 0, 0, "-", "test_utils"]], "test.unit.utils.test_convert_to_array": [[17, 2, 1, "", "Test_convert_to_array"]], "test.unit.utils.test_convert_to_array.Test_convert_to_array": [[17, 3, 1, "", "test_bad_type_cast"], [17, 3, 1, "", "test_convertable_input"], [17, 3, 1, "", "test_panda_handla"], [17, 3, 1, "", "test_unconvertable_input"]], "test.unit.utils.test_sampler_factory": [[17, 2, 1, "", "Test_sampler_factory"]], "test.unit.utils.test_sampler_factory.Test_sampler_factory": [[17, 3, 1, "", "setUpClass"], [17, 3, 1, "", "test_train_test_split"]], "test.unit.utils.test_utils": [[17, 2, 1, "", "Test_utils"]], "test.unit.utils.test_utils.Test_utils": [[17, 3, 1, "", "setUpClass"], [17, 3, 1, "", "test_generate_regression_results_dict"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method", "4": "py:exception"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"], "4": ["py", "exception", "Python exception"]}, "titleterms": {"contribut": [0, 1], "develop": [0, 1], "note": [0, 1], "instal": [0, 1, 9], "version": 0, "check": 0, "test": [0, 1, 10, 11, 12, 13, 14, 15, 16, 17], "ad": 0, "new": 0, "sampler": [0, 3, 4, 5, 9, 14, 15, 16], "Not": 0, "implement": [0, 1], "sampl": [0, 1], "algorithm": [0, 1, 9], "featur": [0, 9], "scheme": 0, "The": 0, "train_val_test_split": [0, 1, 9], "function": [0, 11], "philosophi": 0, "joss": 0, "branch": 0, "onlin": 1, "document": [1, 7], "astart": [1, 2, 3, 4, 5, 6, 7, 8, 9], "pip": 1, "conda": 1, "sourc": 1, "statement": [1, 9], "need": 1, "target": 1, "audienc": 1, "quick": 1, "start": 1, "exampl": 1, "notebook": 1, "withhold": 1, "data": 1, "evalu": 1, "impact": 1, "split": 1, "regress": [1, 12], "model": 1, "us": [1, 9], "categor": 1, "access": 1, "directli": 1, "theori": 1, "applic": 1, "ration": 1, "domain": 1, "specif": 1, "chemic": 1, "molecul": [1, 2], "subpackag": [1, 2, 3, 10, 13, 14], "reproduc": 1, "known": 1, "limit": 1, "how": 1, "cite": 1, "packag": [2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17], "submodul": [2, 3, 4, 5, 6, 11, 12, 15, 16, 17], "main": 2, "modul": [2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17], "content": [2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17], "abstract_sampl": 3, "extrapol": [4, 15], "dbscan": 4, "kmean": 4, "optisim": 4, "scaffold": 4, "sphere_exclus": 4, "time_bas": 4, "interpol": [5, 16], "kennardston": 5, "random_split": 5, "spxy": 5, "util": [6, 17], "array_type_help": 6, "except": 6, "fast_kennard_ston": 6, "sampler_factori": 6, "user_util": 6, "warn": [6, 9], "indic": 7, "tabl": 7, "transit": 9, "from": 9, "sklearn": 9, "step": 9, "1": 9, "2": 9, "chang": 9, "import": 9, "3": 9, "specifi": 9, "an": 9, "4": 9, "pass": 9, "keyword": 9, "argument": 9, "5": 9, "return_indic": 9, "improv": 9, "code": 9, "clariti": 9, "more": 9, "rigor": 9, "ml": 9, "custom": 9, "imperfectsplittingwarn": 9, "normalizationwarn": 9, "test_astart": 11, "test_molecul": 11, "test_regress": 12, "unit": [13, 14, 15, 16, 17], "test_dbscan": 15, "test_scaffold": 15, "test_kmean": 15, "test_optisim": 15, "test_sphere_exclus": 15, "test_time_bas": 15, "test_kennard_ston": 16, "test_random": 16, "test_spxi": 16, "test_convert_to_arrai": 17, "test_sampler_factori": 17, "test_util": 17}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"Contributing & Developer Notes": [[0, "contributing-developer-notes"], [1, "id6"]], "Developer Install": [[0, "developer-install"]], "Version Checking": [[0, "version-checking"]], "Testing": [[0, "testing"]], "Adding New Samplers": [[0, "adding-new-samplers"]], "Not Implemented Sampling Algorithms": [[0, "not-implemented-sampling-algorithms"]], "Adding New Featurization Schemes": [[0, "adding-new-featurization-schemes"]], "The train_val_test_split Function": [[0, "the-train-val-test-split-function"]], "Development Philosophy": [[0, "development-philosophy"]], "JOSS Branch": [[0, "joss-branch"]], "Online Documentation": [[1, "online-documentation"]], "Installing astartes": [[1, "installing-astartes"]], "pip": [[1, "pip"]], "conda": [[1, "conda"]], "Source": [[1, "source"]], "Statement of Need": [[1, "statement-of-need"]], "Target Audience": [[1, "target-audience"]], "Quick Start": [[1, "quick-start"]], "Example Notebooks": [[1, "example-notebooks"]], "Withhold Testing Data with train_val_test_split": [[1, "withhold-testing-data-with-train-val-test-split"]], "Evaluate the Impact of Splitting Algorithms on Regression Models": [[1, "evaluate-the-impact-of-splitting-algorithms-on-regression-models"]], "Using astartes with Categorical Data": [[1, "using-astartes-with-categorical-data"]], "Access Sampling Algorithms Directly": [[1, "access-sampling-algorithms-directly"]], "Theory and Application of astartes": [[1, "theory-and-application-of-astartes"]], "Rational Splitting Algorithms": [[1, "rational-splitting-algorithms"]], "Implemented Sampling Algorithms": [[1, "implemented-sampling-algorithms"]], "Domain-Specific Applications": [[1, "domain-specific-applications"]], "Chemical Data and the astartes.molecules Subpackage": [[1, "chemical-data-and-the-astartes-molecules-subpackage"]], "Reproducibility": [[1, "reproducibility"]], "Known Reproducibility Limitations": [[1, "known-reproducibility-limitations"]], "How to Cite": [[1, "how-to-cite"]], "astartes package": [[2, "astartes-package"]], "Subpackages": [[2, "subpackages"], [3, "subpackages"], [10, "subpackages"], [13, "subpackages"], [14, "subpackages"]], "Submodules": [[2, "submodules"], [3, "submodules"], [4, "submodules"], [5, "submodules"], [6, "submodules"], [11, "submodules"], [12, "submodules"], [15, "submodules"], [16, "submodules"], [17, "submodules"]], "astartes.main module": [[2, "module-astartes.main"]], "astartes.molecules module": [[2, "module-astartes.molecules"]], "Module contents": [[2, "module-astartes"], [3, "module-astartes.samplers"], [4, "module-astartes.samplers.extrapolation"], [5, "module-astartes.samplers.interpolation"], [6, "module-astartes.utils"], [10, "module-test"], [11, "module-test.functional"], [12, "module-test.regression"], [13, "module-test.unit"], [14, "module-test.unit.samplers"], [15, "module-test.unit.samplers.extrapolative"], [16, "module-test.unit.samplers.interpolative"], [17, "module-test.unit.utils"]], "astartes.samplers package": [[3, "astartes-samplers-package"]], "astartes.samplers.abstract_sampler module": [[3, "module-astartes.samplers.abstract_sampler"]], "astartes.samplers.extrapolation package": [[4, "astartes-samplers-extrapolation-package"]], "astartes.samplers.extrapolation.dbscan module": [[4, "module-astartes.samplers.extrapolation.dbscan"]], "astartes.samplers.extrapolation.kmeans module": [[4, "module-astartes.samplers.extrapolation.kmeans"]], "astartes.samplers.extrapolation.optisim module": [[4, "module-astartes.samplers.extrapolation.optisim"]], "astartes.samplers.extrapolation.scaffold module": [[4, "module-astartes.samplers.extrapolation.scaffold"]], "astartes.samplers.extrapolation.sphere_exclusion module": [[4, "module-astartes.samplers.extrapolation.sphere_exclusion"]], "astartes.samplers.extrapolation.time_based module": [[4, "module-astartes.samplers.extrapolation.time_based"]], "astartes.samplers.interpolation package": [[5, "astartes-samplers-interpolation-package"]], "astartes.samplers.interpolation.kennardstone module": [[5, "module-astartes.samplers.interpolation.kennardstone"]], "astartes.samplers.interpolation.random_split module": [[5, "module-astartes.samplers.interpolation.random_split"]], "astartes.samplers.interpolation.spxy module": [[5, "module-astartes.samplers.interpolation.spxy"]], "astartes.utils package": [[6, "astartes-utils-package"]], "astartes.utils.array_type_helpers module": [[6, "module-astartes.utils.array_type_helpers"]], "astartes.utils.exceptions module": [[6, "module-astartes.utils.exceptions"]], "astartes.utils.fast_kennard_stone module": [[6, "module-astartes.utils.fast_kennard_stone"]], "astartes.utils.sampler_factory module": [[6, "module-astartes.utils.sampler_factory"]], "astartes.utils.user_utils module": [[6, "module-astartes.utils.user_utils"]], "astartes.utils.warnings module": [[6, "module-astartes.utils.warnings"]], "astartes documentation": [[7, "astartes-documentation"]], "Contents:": [[7, null]], "Indices and tables": [[7, "indices-and-tables"]], "astartes": [[8, "astartes"]], "Transitioning from sklearn to astartes": [[9, "transitioning-from-sklearn-to-astartes"]], "Step 1. Installation": [[9, "step-1-installation"]], "Step 2. Changing the import Statement": [[9, "step-2-changing-the-import-statement"]], "Step 3. Specifying an Algorithmic Sampler": [[9, "step-3-specifying-an-algorithmic-sampler"]], "Step 4. Passing Keyword Arguments": [[9, "step-4-passing-keyword-arguments"]], "Step 5. Useful astartes Features": [[9, "step-5-useful-astartes-features"]], "return_indices: Improve Code Clarity": [[9, "return-indices-improve-code-clarity"]], "train_val_test_split: More Rigorous ML": [[9, "train-val-test-split-more-rigorous-ml"]], "Custom Warnings: ImperfectSplittingWarning and NormalizationWarning": [[9, "custom-warnings-imperfectsplittingwarning-and-normalizationwarning"]], "test package": [[10, "test-package"]], "test.functional package": [[11, "test-functional-package"]], "test.functional.test_astartes module": [[11, "module-test.functional.test_astartes"]], "test.functional.test_molecules module": [[11, "module-test.functional.test_molecules"]], "test.regression package": [[12, "test-regression-package"]], "test.regression.test_regression module": [[12, "module-test.regression.test_regression"]], "test.unit package": [[13, "test-unit-package"]], "test.unit.samplers package": [[14, "test-unit-samplers-package"]], "test.unit.samplers.extrapolative package": [[15, "test-unit-samplers-extrapolative-package"]], "test.unit.samplers.extrapolative.test_DBSCAN module": [[15, "module-test.unit.samplers.extrapolative.test_DBSCAN"]], "test.unit.samplers.extrapolative.test_Scaffold module": [[15, "module-test.unit.samplers.extrapolative.test_Scaffold"]], "test.unit.samplers.extrapolative.test_kmeans module": [[15, "module-test.unit.samplers.extrapolative.test_kmeans"]], "test.unit.samplers.extrapolative.test_optisim module": [[15, "module-test.unit.samplers.extrapolative.test_optisim"]], "test.unit.samplers.extrapolative.test_sphere_exclusion module": [[15, "module-test.unit.samplers.extrapolative.test_sphere_exclusion"]], "test.unit.samplers.extrapolative.test_time_based module": [[15, "module-test.unit.samplers.extrapolative.test_time_based"]], "test.unit.samplers.interpolative package": [[16, "test-unit-samplers-interpolative-package"]], "test.unit.samplers.interpolative.test_kennard_stone module": [[16, "module-test.unit.samplers.interpolative.test_kennard_stone"]], "test.unit.samplers.interpolative.test_random module": [[16, "module-test.unit.samplers.interpolative.test_random"]], "test.unit.samplers.interpolative.test_spxy module": [[16, "module-test.unit.samplers.interpolative.test_spxy"]], "test.unit.utils package": [[17, "test-unit-utils-package"]], "test.unit.utils.test_convert_to_array module": [[17, "module-test.unit.utils.test_convert_to_array"]], "test.unit.utils.test_sampler_factory module": [[17, "module-test.unit.utils.test_sampler_factory"]], "test.unit.utils.test_utils module": [[17, "module-test.unit.utils.test_utils"]]}, "indexentries": {"astartes": [[2, "module-astartes"]], "astartes.main": [[2, "module-astartes.main"]], "astartes.molecules": [[2, "module-astartes.molecules"]], "module": [[2, "module-astartes"], [2, "module-astartes.main"], [2, "module-astartes.molecules"], [3, "module-astartes.samplers"], [3, "module-astartes.samplers.abstract_sampler"], [4, "module-astartes.samplers.extrapolation"], [4, "module-astartes.samplers.extrapolation.dbscan"], [4, "module-astartes.samplers.extrapolation.kmeans"], [4, "module-astartes.samplers.extrapolation.optisim"], [4, "module-astartes.samplers.extrapolation.scaffold"], [4, "module-astartes.samplers.extrapolation.sphere_exclusion"], [4, "module-astartes.samplers.extrapolation.time_based"], [5, "module-astartes.samplers.interpolation"], [5, "module-astartes.samplers.interpolation.kennardstone"], [5, "module-astartes.samplers.interpolation.random_split"], [5, "module-astartes.samplers.interpolation.spxy"], [6, "module-astartes.utils"], [6, "module-astartes.utils.array_type_helpers"], [6, "module-astartes.utils.exceptions"], [6, "module-astartes.utils.fast_kennard_stone"], [6, "module-astartes.utils.sampler_factory"], [6, "module-astartes.utils.user_utils"], [6, "module-astartes.utils.warnings"], [10, "module-test"], [11, "module-test.functional"], [11, "module-test.functional.test_astartes"], [11, "module-test.functional.test_molecules"], [12, "module-test.regression"], [12, "module-test.regression.test_regression"], [13, "module-test.unit"], [14, "module-test.unit.samplers"], [15, "module-test.unit.samplers.extrapolative"], [15, "module-test.unit.samplers.extrapolative.test_DBSCAN"], [15, "module-test.unit.samplers.extrapolative.test_Scaffold"], [15, "module-test.unit.samplers.extrapolative.test_kmeans"], [15, "module-test.unit.samplers.extrapolative.test_optisim"], [15, "module-test.unit.samplers.extrapolative.test_sphere_exclusion"], [15, "module-test.unit.samplers.extrapolative.test_time_based"], [16, "module-test.unit.samplers.interpolative"], [16, "module-test.unit.samplers.interpolative.test_kennard_stone"], [16, "module-test.unit.samplers.interpolative.test_random"], [16, "module-test.unit.samplers.interpolative.test_spxy"], [17, "module-test.unit.utils"], [17, "module-test.unit.utils.test_convert_to_array"], [17, "module-test.unit.utils.test_sampler_factory"], [17, "module-test.unit.utils.test_utils"]], "train_test_split() (in module astartes.main)": [[2, "astartes.main.train_test_split"]], "train_test_split_molecules() (in module astartes.molecules)": [[2, "astartes.molecules.train_test_split_molecules"]], "train_val_test_split() (in module astartes.main)": [[2, "astartes.main.train_val_test_split"]], "train_val_test_split_molecules() (in module astartes.molecules)": [[2, "astartes.molecules.train_val_test_split_molecules"]], "abstractsampler (class in astartes.samplers.abstract_sampler)": [[3, "astartes.samplers.abstract_sampler.AbstractSampler"]], "__init__() (astartes.samplers.abstract_sampler.abstractsampler method)": [[3, "astartes.samplers.abstract_sampler.AbstractSampler.__init__"]], "astartes.samplers": [[3, "module-astartes.samplers"]], "astartes.samplers.abstract_sampler": [[3, "module-astartes.samplers.abstract_sampler"]], "get_clusters() (astartes.samplers.abstract_sampler.abstractsampler method)": [[3, "astartes.samplers.abstract_sampler.AbstractSampler.get_clusters"]], "get_config() (astartes.samplers.abstract_sampler.abstractsampler method)": [[3, "astartes.samplers.abstract_sampler.AbstractSampler.get_config"]], "get_sample_idxs() (astartes.samplers.abstract_sampler.abstractsampler method)": [[3, "astartes.samplers.abstract_sampler.AbstractSampler.get_sample_idxs"]], "get_sorted_cluster_counter() (astartes.samplers.abstract_sampler.abstractsampler method)": [[3, "astartes.samplers.abstract_sampler.AbstractSampler.get_sorted_cluster_counter"]], "dbscan (class in astartes.samplers.extrapolation.dbscan)": [[4, "astartes.samplers.extrapolation.dbscan.DBSCAN"]], "kmeans (class in astartes.samplers.extrapolation.kmeans)": [[4, "astartes.samplers.extrapolation.kmeans.KMeans"]], "optisim (class in astartes.samplers.extrapolation.optisim)": [[4, "astartes.samplers.extrapolation.optisim.OptiSim"]], "scaffold (class in astartes.samplers.extrapolation.scaffold)": [[4, "astartes.samplers.extrapolation.scaffold.Scaffold"]], "sphereexclusion (class in astartes.samplers.extrapolation.sphere_exclusion)": [[4, "astartes.samplers.extrapolation.sphere_exclusion.SphereExclusion"]], "timebased (class in astartes.samplers.extrapolation.time_based)": [[4, "astartes.samplers.extrapolation.time_based.TimeBased"]], "astartes.samplers.extrapolation": [[4, "module-astartes.samplers.extrapolation"]], "astartes.samplers.extrapolation.dbscan": [[4, "module-astartes.samplers.extrapolation.dbscan"]], "astartes.samplers.extrapolation.kmeans": [[4, "module-astartes.samplers.extrapolation.kmeans"]], "astartes.samplers.extrapolation.optisim": [[4, "module-astartes.samplers.extrapolation.optisim"]], "astartes.samplers.extrapolation.scaffold": [[4, "module-astartes.samplers.extrapolation.scaffold"]], "astartes.samplers.extrapolation.sphere_exclusion": [[4, "module-astartes.samplers.extrapolation.sphere_exclusion"]], "astartes.samplers.extrapolation.time_based": [[4, "module-astartes.samplers.extrapolation.time_based"]], "generate_bemis_murcko_scaffold() (astartes.samplers.extrapolation.scaffold.scaffold method)": [[4, "astartes.samplers.extrapolation.scaffold.Scaffold.generate_bemis_murcko_scaffold"]], "get_dist() (astartes.samplers.extrapolation.optisim.optisim method)": [[4, "astartes.samplers.extrapolation.optisim.OptiSim.get_dist"]], "move_item() (astartes.samplers.extrapolation.optisim.optisim method)": [[4, "astartes.samplers.extrapolation.optisim.OptiSim.move_item"]], "rchoose() (astartes.samplers.extrapolation.optisim.optisim method)": [[4, "astartes.samplers.extrapolation.optisim.OptiSim.rchoose"]], "scaffold_to_smiles() (astartes.samplers.extrapolation.scaffold.scaffold method)": [[4, "astartes.samplers.extrapolation.scaffold.Scaffold.scaffold_to_smiles"]], "str_to_mol() (astartes.samplers.extrapolation.scaffold.scaffold method)": [[4, "astartes.samplers.extrapolation.scaffold.Scaffold.str_to_mol"]], "kennardstone (class in astartes.samplers.interpolation.kennardstone)": [[5, "astartes.samplers.interpolation.kennardstone.KennardStone"]], "random (class in astartes.samplers.interpolation.random_split)": [[5, "astartes.samplers.interpolation.random_split.Random"]], "spxy (class in astartes.samplers.interpolation.spxy)": [[5, "astartes.samplers.interpolation.spxy.SPXY"]], "astartes.samplers.interpolation": [[5, "module-astartes.samplers.interpolation"]], "astartes.samplers.interpolation.kennardstone": [[5, "module-astartes.samplers.interpolation.kennardstone"]], "astartes.samplers.interpolation.random_split": [[5, "module-astartes.samplers.interpolation.random_split"]], "astartes.samplers.interpolation.spxy": [[5, "module-astartes.samplers.interpolation.spxy"]], "conversionwarning": [[6, "astartes.utils.warnings.ConversionWarning"]], "imperfectsplittingwarning": [[6, "astartes.utils.warnings.ImperfectSplittingWarning"]], "invalidconfigurationerror": [[6, "astartes.utils.exceptions.InvalidConfigurationError"]], "invalidmodeltypeerror": [[6, "astartes.utils.exceptions.InvalidModelTypeError"]], "moleculesnotinstallederror": [[6, "astartes.utils.exceptions.MoleculesNotInstalledError"]], "nomatchingscaffold": [[6, "astartes.utils.warnings.NoMatchingScaffold"]], "normalizationwarning": [[6, "astartes.utils.warnings.NormalizationWarning"]], "samplerfactory (class in astartes.utils.sampler_factory)": [[6, "astartes.utils.sampler_factory.SamplerFactory"]], "samplernotimplementederror": [[6, "astartes.utils.exceptions.SamplerNotImplementedError"]], "uncastableinputerror": [[6, "astartes.utils.exceptions.UncastableInputError"]], "__init__() (astartes.utils.exceptions.invalidconfigurationerror method)": [[6, "astartes.utils.exceptions.InvalidConfigurationError.__init__"]], "__init__() (astartes.utils.exceptions.invalidmodeltypeerror method)": [[6, "astartes.utils.exceptions.InvalidModelTypeError.__init__"]], "__init__() (astartes.utils.exceptions.moleculesnotinstallederror method)": [[6, "astartes.utils.exceptions.MoleculesNotInstalledError.__init__"]], "__init__() (astartes.utils.exceptions.samplernotimplementederror method)": [[6, "astartes.utils.exceptions.SamplerNotImplementedError.__init__"]], "__init__() (astartes.utils.exceptions.uncastableinputerror method)": [[6, "astartes.utils.exceptions.UncastableInputError.__init__"]], "__init__() (astartes.utils.sampler_factory.samplerfactory method)": [[6, "astartes.utils.sampler_factory.SamplerFactory.__init__"]], "__init__() (astartes.utils.warnings.conversionwarning method)": [[6, "astartes.utils.warnings.ConversionWarning.__init__"]], "__init__() (astartes.utils.warnings.imperfectsplittingwarning method)": [[6, "astartes.utils.warnings.ImperfectSplittingWarning.__init__"]], "__init__() (astartes.utils.warnings.nomatchingscaffold method)": [[6, "astartes.utils.warnings.NoMatchingScaffold.__init__"]], "__init__() (astartes.utils.warnings.normalizationwarning method)": [[6, "astartes.utils.warnings.NormalizationWarning.__init__"]], "astartes.utils": [[6, "module-astartes.utils"]], "astartes.utils.array_type_helpers": [[6, "module-astartes.utils.array_type_helpers"]], "astartes.utils.exceptions": [[6, "module-astartes.utils.exceptions"]], "astartes.utils.fast_kennard_stone": [[6, "module-astartes.utils.fast_kennard_stone"]], "astartes.utils.sampler_factory": [[6, "module-astartes.utils.sampler_factory"]], "astartes.utils.user_utils": [[6, "module-astartes.utils.user_utils"]], "astartes.utils.warnings": [[6, "module-astartes.utils.warnings"]], "convert_to_array() (in module astartes.utils.array_type_helpers)": [[6, "astartes.utils.array_type_helpers.convert_to_array"]], "display_results_as_table() (in module astartes.utils.user_utils)": [[6, "astartes.utils.user_utils.display_results_as_table"]], "fast_kennard_stone() (in module astartes.utils.fast_kennard_stone)": [[6, "astartes.utils.fast_kennard_stone.fast_kennard_stone"]], "generate_regression_results_dict() (in module astartes.utils)": [[6, "astartes.utils.generate_regression_results_dict"]], "generate_regression_results_dict() (in module astartes.utils.user_utils)": [[6, "astartes.utils.user_utils.generate_regression_results_dict"]], "get_sampler() (astartes.utils.sampler_factory.samplerfactory method)": [[6, "astartes.utils.sampler_factory.SamplerFactory.get_sampler"]], "panda_handla() (in module astartes.utils.array_type_helpers)": [[6, "astartes.utils.array_type_helpers.panda_handla"]], "return_helper() (in module astartes.utils.array_type_helpers)": [[6, "astartes.utils.array_type_helpers.return_helper"]], "test": [[10, "module-test"]], "test_astartes (class in test.functional.test_astartes)": [[11, "test.functional.test_astartes.Test_astartes"]], "test_molecules (class in test.functional.test_molecules)": [[11, "test.functional.test_molecules.Test_molecules"]], "setupclass() (test.functional.test_astartes.test_astartes class method)": [[11, "test.functional.test_astartes.Test_astartes.setUpClass"]], "setupclass() (test.functional.test_molecules.test_molecules class method)": [[11, "test.functional.test_molecules.Test_molecules.setUpClass"]], "test.functional": [[11, "module-test.functional"]], "test.functional.test_astartes": [[11, "module-test.functional.test_astartes"]], "test.functional.test_molecules": [[11, "module-test.functional.test_molecules"]], "test_close_mispelling_sampler() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_close_mispelling_sampler"]], "test_fingerprints() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_fingerprints"]], "test_fprint_hopts() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_fprint_hopts"]], "test_inconsistent_input_lengths() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_inconsistent_input_lengths"]], "test_insufficient_dataset_test() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_insufficient_dataset_test"]], "test_insufficient_dataset_train() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_insufficient_dataset_train"]], "test_insufficient_dataset_val() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_insufficient_dataset_val"]], "test_maximum_call() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_maximum_call"]], "test_molecules() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_molecules"]], "test_molecules_with_rdkit() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_molecules_with_rdkit"]], "test_molecules_with_troublesome_smiles() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_molecules_with_troublesome_smiles"]], "test_not_implemented_sampler() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_not_implemented_sampler"]], "test_return_indices() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_return_indices"]], "test_return_indices_with_validation() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_return_indices_with_validation"]], "test_sampler_hopts() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_sampler_hopts"]], "test_split_validation() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_split_validation"]], "test_train_test_split() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_train_test_split"]], "test_train_val_test_split() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_train_val_test_split"]], "test_train_val_test_split_extrpolation_shuffling() (test.functional.test_astartes.test_astartes method)": [[11, "test.functional.test_astartes.Test_astartes.test_train_val_test_split_extrpolation_shuffling"]], "test_validation_split_molecules() (test.functional.test_molecules.test_molecules method)": [[11, "test.functional.test_molecules.Test_molecules.test_validation_split_molecules"]], "test_regression (class in test.regression.test_regression)": [[12, "test.regression.test_regression.Test_regression"]], "setupclass() (test.regression.test_regression.test_regression class method)": [[12, "test.regression.test_regression.Test_regression.setUpClass"]], "test.regression": [[12, "module-test.regression"]], "test.regression.test_regression": [[12, "module-test.regression.test_regression"]], "test_extrapolation_regression() (test.regression.test_regression.test_regression method)": [[12, "test.regression.test_regression.Test_regression.test_extrapolation_regression"]], "test_interpolation_regression() (test.regression.test_regression.test_regression method)": [[12, "test.regression.test_regression.Test_regression.test_interpolation_regression"]], "test_kmeans_regression_sklearn_v12() (test.regression.test_regression.test_regression method)": [[12, "test.regression.test_regression.Test_regression.test_kmeans_regression_sklearn_v12"]], "test_kmeans_regression_sklearn_v13() (test.regression.test_regression.test_regression method)": [[12, "test.regression.test_regression.Test_regression.test_kmeans_regression_sklearn_v13"]], "test_timebased_regression() (test.regression.test_regression.test_regression method)": [[12, "test.regression.test_regression.Test_regression.test_timebased_regression"]], "test.unit": [[13, "module-test.unit"]], "test.unit.samplers": [[14, "module-test.unit.samplers"]], "test_dbscan (class in test.unit.samplers.extrapolative.test_dbscan)": [[15, "test.unit.samplers.extrapolative.test_DBSCAN.Test_DBSCAN"]], "test_kmeans (class in test.unit.samplers.extrapolative.test_kmeans)": [[15, "test.unit.samplers.extrapolative.test_kmeans.Test_kmeans"]], "test_optisim (class in test.unit.samplers.extrapolative.test_optisim)": [[15, "test.unit.samplers.extrapolative.test_optisim.Test_optisim"]], "test_scaffold (class in test.unit.samplers.extrapolative.test_scaffold)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold"]], "test_sphere_exclusion (class in test.unit.samplers.extrapolative.test_sphere_exclusion)": [[15, "test.unit.samplers.extrapolative.test_sphere_exclusion.Test_sphere_exclusion"]], "test_time_based (class in test.unit.samplers.extrapolative.test_time_based)": [[15, "test.unit.samplers.extrapolative.test_time_based.Test_time_based"]], "setupclass() (test.unit.samplers.extrapolative.test_dbscan.test_dbscan class method)": [[15, "test.unit.samplers.extrapolative.test_DBSCAN.Test_DBSCAN.setUpClass"]], "setupclass() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold class method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.setUpClass"]], "setupclass() (test.unit.samplers.extrapolative.test_kmeans.test_kmeans class method)": [[15, "test.unit.samplers.extrapolative.test_kmeans.Test_kmeans.setUpClass"]], "setupclass() (test.unit.samplers.extrapolative.test_optisim.test_optisim class method)": [[15, "test.unit.samplers.extrapolative.test_optisim.Test_optisim.setUpClass"]], "setupclass() (test.unit.samplers.extrapolative.test_sphere_exclusion.test_sphere_exclusion class method)": [[15, "test.unit.samplers.extrapolative.test_sphere_exclusion.Test_sphere_exclusion.setUpClass"]], "setupclass() (test.unit.samplers.extrapolative.test_time_based.test_time_based class method)": [[15, "test.unit.samplers.extrapolative.test_time_based.Test_time_based.setUpClass"]], "test.unit.samplers.extrapolative": [[15, "module-test.unit.samplers.extrapolative"]], "test.unit.samplers.extrapolative.test_dbscan": [[15, "module-test.unit.samplers.extrapolative.test_DBSCAN"]], "test.unit.samplers.extrapolative.test_scaffold": [[15, "module-test.unit.samplers.extrapolative.test_Scaffold"]], "test.unit.samplers.extrapolative.test_kmeans": [[15, "module-test.unit.samplers.extrapolative.test_kmeans"]], "test.unit.samplers.extrapolative.test_optisim": [[15, "module-test.unit.samplers.extrapolative.test_optisim"]], "test.unit.samplers.extrapolative.test_sphere_exclusion": [[15, "module-test.unit.samplers.extrapolative.test_sphere_exclusion"]], "test.unit.samplers.extrapolative.test_time_based": [[15, "module-test.unit.samplers.extrapolative.test_time_based"]], "test_dbscan() (test.unit.samplers.extrapolative.test_dbscan.test_dbscan method)": [[15, "test.unit.samplers.extrapolative.test_DBSCAN.Test_DBSCAN.test_dbscan"]], "test_dbscan_sampling() (test.unit.samplers.extrapolative.test_dbscan.test_dbscan method)": [[15, "test.unit.samplers.extrapolative.test_DBSCAN.Test_DBSCAN.test_dbscan_sampling"]], "test_include_chirality() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.test_include_chirality"]], "test_incorrect_input() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.test_incorrect_input"]], "test_incorrect_input() (test.unit.samplers.extrapolative.test_time_based.test_time_based method)": [[15, "test.unit.samplers.extrapolative.test_time_based.Test_time_based.test_incorrect_input"]], "test_kmeans() (test.unit.samplers.extrapolative.test_kmeans.test_kmeans method)": [[15, "test.unit.samplers.extrapolative.test_kmeans.Test_kmeans.test_kmeans"]], "test_kmeans_sampling_v12() (test.unit.samplers.extrapolative.test_kmeans.test_kmeans method)": [[15, "test.unit.samplers.extrapolative.test_kmeans.Test_kmeans.test_kmeans_sampling_v12"]], "test_kmeans_sampling_v13() (test.unit.samplers.extrapolative.test_kmeans.test_kmeans method)": [[15, "test.unit.samplers.extrapolative.test_kmeans.Test_kmeans.test_kmeans_sampling_v13"]], "test_mising_labels() (test.unit.samplers.extrapolative.test_time_based.test_time_based method)": [[15, "test.unit.samplers.extrapolative.test_time_based.Test_time_based.test_mising_labels"]], "test_mol_from_inchi() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.test_mol_from_inchi"]], "test_no_scaffold_found_warning() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.test_no_scaffold_found_warning"]], "test_optisim() (test.unit.samplers.extrapolative.test_optisim.test_optisim method)": [[15, "test.unit.samplers.extrapolative.test_optisim.Test_optisim.test_optisim"]], "test_optisim_sampling() (test.unit.samplers.extrapolative.test_optisim.test_optisim method)": [[15, "test.unit.samplers.extrapolative.test_optisim.Test_optisim.test_optisim_sampling"]], "test_remove_atom_map() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.test_remove_atom_map"]], "test_scaffold() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.test_scaffold"]], "test_scaffold_sampling() (test.unit.samplers.extrapolative.test_scaffold.test_scaffold method)": [[15, "test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold.test_scaffold_sampling"]], "test_sphereexclusion() (test.unit.samplers.extrapolative.test_sphere_exclusion.test_sphere_exclusion method)": [[15, "test.unit.samplers.extrapolative.test_sphere_exclusion.Test_sphere_exclusion.test_sphereexclusion"]], "test_sphereexclusion_sampling() (test.unit.samplers.extrapolative.test_sphere_exclusion.test_sphere_exclusion method)": [[15, "test.unit.samplers.extrapolative.test_sphere_exclusion.Test_sphere_exclusion.test_sphereexclusion_sampling"]], "test_time_based_date() (test.unit.samplers.extrapolative.test_time_based.test_time_based method)": [[15, "test.unit.samplers.extrapolative.test_time_based.Test_time_based.test_time_based_date"]], "test_time_based_datetime() (test.unit.samplers.extrapolative.test_time_based.test_time_based method)": [[15, "test.unit.samplers.extrapolative.test_time_based.Test_time_based.test_time_based_datetime"]], "test_time_based_sampling() (test.unit.samplers.extrapolative.test_time_based.test_time_based method)": [[15, "test.unit.samplers.extrapolative.test_time_based.Test_time_based.test_time_based_sampling"]], "test_spxy (class in test.unit.samplers.interpolative.test_spxy)": [[16, "test.unit.samplers.interpolative.test_spxy.Test_SPXY"]], "test_kennard_stone (class in test.unit.samplers.interpolative.test_kennard_stone)": [[16, "test.unit.samplers.interpolative.test_kennard_stone.Test_kennard_stone"]], "test_random (class in test.unit.samplers.interpolative.test_random)": [[16, "test.unit.samplers.interpolative.test_random.Test_random"]], "setupclass() (test.unit.samplers.interpolative.test_kennard_stone.test_kennard_stone class method)": [[16, "test.unit.samplers.interpolative.test_kennard_stone.Test_kennard_stone.setUpClass"]], "setupclass() (test.unit.samplers.interpolative.test_random.test_random class method)": [[16, "test.unit.samplers.interpolative.test_random.Test_random.setUpClass"]], "setupclass() (test.unit.samplers.interpolative.test_spxy.test_spxy class method)": [[16, "test.unit.samplers.interpolative.test_spxy.Test_SPXY.setUpClass"]], "test.unit.samplers.interpolative": [[16, "module-test.unit.samplers.interpolative"]], "test.unit.samplers.interpolative.test_kennard_stone": [[16, "module-test.unit.samplers.interpolative.test_kennard_stone"]], "test.unit.samplers.interpolative.test_random": [[16, "module-test.unit.samplers.interpolative.test_random"]], "test.unit.samplers.interpolative.test_spxy": [[16, "module-test.unit.samplers.interpolative.test_spxy"]], "test_kennard_stone() (test.unit.samplers.interpolative.test_kennard_stone.test_kennard_stone method)": [[16, "test.unit.samplers.interpolative.test_kennard_stone.Test_kennard_stone.test_kennard_stone"]], "test_kennard_stone_sample() (test.unit.samplers.interpolative.test_kennard_stone.test_kennard_stone method)": [[16, "test.unit.samplers.interpolative.test_kennard_stone.Test_kennard_stone.test_kennard_stone_sample"]], "test_kennard_stone_sample_no_warning() (test.unit.samplers.interpolative.test_kennard_stone.test_kennard_stone method)": [[16, "test.unit.samplers.interpolative.test_kennard_stone.Test_kennard_stone.test_kennard_stone_sample_no_warning"]], "test_missing_y() (test.unit.samplers.interpolative.test_spxy.test_spxy method)": [[16, "test.unit.samplers.interpolative.test_spxy.Test_SPXY.test_missing_y"]], "test_random() (test.unit.samplers.interpolative.test_random.test_random method)": [[16, "test.unit.samplers.interpolative.test_random.Test_random.test_random"]], "test_random_sample() (test.unit.samplers.interpolative.test_random.test_random method)": [[16, "test.unit.samplers.interpolative.test_random.Test_random.test_random_sample"]], "test_random_sample_no_warning() (test.unit.samplers.interpolative.test_random.test_random method)": [[16, "test.unit.samplers.interpolative.test_random.Test_random.test_random_sample_no_warning"]], "test_spxy() (test.unit.samplers.interpolative.test_spxy.test_spxy method)": [[16, "test.unit.samplers.interpolative.test_spxy.Test_SPXY.test_spxy"]], "test_spxy_sampling() (test.unit.samplers.interpolative.test_spxy.test_spxy method)": [[16, "test.unit.samplers.interpolative.test_spxy.Test_SPXY.test_spxy_sampling"]], "test_convert_to_array (class in test.unit.utils.test_convert_to_array)": [[17, "test.unit.utils.test_convert_to_array.Test_convert_to_array"]], "test_sampler_factory (class in test.unit.utils.test_sampler_factory)": [[17, "test.unit.utils.test_sampler_factory.Test_sampler_factory"]], "test_utils (class in test.unit.utils.test_utils)": [[17, "test.unit.utils.test_utils.Test_utils"]], "setupclass() (test.unit.utils.test_sampler_factory.test_sampler_factory class method)": [[17, "test.unit.utils.test_sampler_factory.Test_sampler_factory.setUpClass"]], "setupclass() (test.unit.utils.test_utils.test_utils class method)": [[17, "test.unit.utils.test_utils.Test_utils.setUpClass"]], "test.unit.utils": [[17, "module-test.unit.utils"]], "test.unit.utils.test_convert_to_array": [[17, "module-test.unit.utils.test_convert_to_array"]], "test.unit.utils.test_sampler_factory": [[17, "module-test.unit.utils.test_sampler_factory"]], "test.unit.utils.test_utils": [[17, "module-test.unit.utils.test_utils"]], "test_bad_type_cast() (test.unit.utils.test_convert_to_array.test_convert_to_array method)": [[17, "test.unit.utils.test_convert_to_array.Test_convert_to_array.test_bad_type_cast"]], "test_convertable_input() (test.unit.utils.test_convert_to_array.test_convert_to_array method)": [[17, "test.unit.utils.test_convert_to_array.Test_convert_to_array.test_convertable_input"]], "test_generate_regression_results_dict() (test.unit.utils.test_utils.test_utils method)": [[17, "test.unit.utils.test_utils.Test_utils.test_generate_regression_results_dict"]], "test_panda_handla() (test.unit.utils.test_convert_to_array.test_convert_to_array method)": [[17, "test.unit.utils.test_convert_to_array.Test_convert_to_array.test_panda_handla"]], "test_train_test_split() (test.unit.utils.test_sampler_factory.test_sampler_factory method)": [[17, "test.unit.utils.test_sampler_factory.Test_sampler_factory.test_train_test_split"]], "test_unconvertable_input() (test.unit.utils.test_convert_to_array.test_convert_to_array method)": [[17, "test.unit.utils.test_convert_to_array.Test_convert_to_array.test_unconvertable_input"]]}}) \ No newline at end of file diff --git a/docs/sklearn_to_astartes.doctree b/docs/sklearn_to_astartes.doctree new file mode 100644 index 0000000000000000000000000000000000000000..36bcf04a9df61dc693a88d6617a389b67287b013 GIT binary patch literal 32206 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 + + + + + + Transitioning from sklearn to astartes — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Transitioning from sklearn to astartes

+
+

Step 1. Installation

+

astartes has been designed to rely on (1) as few packages as possible and (2) packages which are already likely to be installed in a Machine Learning (ML) Python workflow (i.e. Numpy and Sklearn). Because of this, astartes should be compatible with your existing workflow such as a conda environment.

+

To install astartes for general ML use (the sampling of arbitrary vectors): **pip install astartes**

+

For users in cheminformatics, astartes has an optional add-on that includes featurization as part of the sampling. To install, type **pip install 'astartes[molecules]'**. With this extra install, astartes uses ``AIMSim` <https://vlachosgroup.github.io/AIMSim/README.html>`_ to encode SMILES strings as feature vectors. The SMILES strings are parsed into molecular graphs using RDKit and then sampled with a single function call: train_test_split_molecules.

+
    +
  • If your workflow already has a featurization scheme in place (i.e. you already have a vector representation of your chemical of interest), you can directly use train_test_split (though we invite you to explore the many molecular descriptors made available through AIMSim).

  • +
+
+
+

Step 2. Changing the import Statement

+

In one of the first few lines of your Python script, you have the line from sklearn.model_selection import train_test_split. To switch to using astartes change this line to from astartes import train_test_split.

+

That’s it! You are now using astartes.

+

If you were just calling train_test_split(X, y), your script should now work in the exact same way as sklearn with no changes required.

+
X_train, X_test, y_train, y_test = train_test_split(
+    X,
+    y,
+    random_state=42,
+)
+
+
+

becomes

+
X_train, X_test, y_train, y_test = train_test_split(
+    X,
+    y,
+    random_state=42,
+)
+
+
+

But we encourage you to try one of our many other samplers (see below)!

+
+
+

Step 3. Specifying an Algorithmic Sampler

+

By default (for interoperability), astartes will use a random sampler to produce train/test splits - but the real value of astartes is in the algorithmic sampling algorithms it implements. Check out the README for a complete list of available algorithms and how to call and customize them.

+

If you existing call to train_test_split looks like this:

+
X_train, X_test, y_train, y_test = train_test_split(
+    X,
+    y,
+)
+
+
+

and you want to try out using Kennard-Stone sampling, switch it to this:

+
X_train, X_test, y_train, y_test = train_test_split(
+    X,
+    y,
+    sampler="kennard_stone",
+)
+
+
+

That’s it!

+
+
+

Step 4. Passing Keyword Arguments

+

All of the arguments to the sklearn‘s train_test_split can still be passed to astartestrain_test_split:

+
X_train, X_test, y_train, y_test, labels_train, labels_test = train_test_split(
+    X,
+    y,
+    labels,
+    train_size = 0.75,
+    test_size = 0.25,
+    sampler = "kmeans",
+    hopts = {"n_clusters": 4},
+)
+
+
+

Some samplers have tunable hyperparameters that allow you to more finely control their behavior. To do this with Sphere Exclusion, for example, switch your call to this:

+
X_train, X_test, y_train, y_test = train_test_split(
+    X,
+    y,
+    sampler="sphere_exclusion",
+    hopts={"distance_cutoff":0.15},
+)
+
+
+
+
+

Step 5. Useful astartes Features

+
+

return_indices: Improve Code Clarity

+

There are circumstances where the indices of the train/test data can be useful (for example, if y or labels are large, memory-intense objects), and there is no way to directly return these indices in sklearn. astartes will return the sampling splits themselves by default, but it can also return the indices for the user to manipulate according to their needs:

+
X_train, X_test, y_train, y_test, labels_train, labels_test = train_test_split(
+    X,
+    y,
+    labels,
+    return_indices = False,
+)
+
+
+

could instead be

+
X_train, X_test, y_train, y_test, labels_train, labels_test, indices_train, indices_test = train_test_split(
+    X,
+    y,
+    labels,
+    return_indices = True,
+)
+
+
+

If y or labels were large, memory-intense objects it could be beneficial to not pass them in to train_test_split and instead separate the existing lists later using the returned indices.

+
+
+

train_val_test_split: More Rigorous ML

+

Behind the scenes, train_test_split is actually just a one-line function that calls the real workhorse of astartes - train_val_test_split:

+
def train_test_split(
+    X: np.array,
+    ...
+    return_indices: bool = False,
+):
+    return train_val_test_split(
+        X, y, labels, train_size, 0, test_size, sampler, hopts, return_indices
+    )
+
+
+

The function call to train_val_test_split is identical to train_test_split and supports all the same samplers and hyperparameters, except for one additional keyword argument val_size:

+
def train_val_test_split(
+    X: np.array,
+    y: np.array = None,
+    labels: np.array = None,
+    train_size: float = 0.8,
+    val_size: float = 0.1,
+    test_size: float = 0.1,
+    sampler: str = "random",
+    hopts: dict = {},
+    return_indices: bool = False,
+):
+
+
+

When called, this will return three arrays from X, y, and labels (or three arrays of indices, if return_indices=True) rather than the usual two, according to the values given for train_size, val_size, and test_size in the function call.

+
X_train, X_val, X_test, y_train, y_val, y_test = train_val_test_split(
+    X,
+    y,
+    train_size: float = 0.8,
+    val_size: float = 0.1,
+    test_size: float = 0.1,
+)
+
+
+

For truly rigorous ML modeling, the validation set should be used for hyperparameter tuning and the test set held out until the very final change has been made to the model to get a true sense of its performance. For better or for worse, this is not the current standard for ML modeling, but the authors believe it should be.

+
+
+

Custom Warnings: ImperfectSplittingWarning and NormalizationWarning

+

In the event that your requested train/validation/test split is not mathematically possible given the dimensions of the input data (i.e. you request 50/25/25 but have 101 data points), astartes will warn you during runtime that it has occurred. sklearn simply moves on quietly, and while this is fine most of the time, the authors felt it prudent to warn the user. +When entering a train/validation/test split, astartes will check that it is normalized and make it so if not, warning the user during runtime. This will hopefully help prevent head-scratching hours of debugging.

+
+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sklearn_to_astartes.rst b/docs/sklearn_to_astartes.rst new file mode 100644 index 00000000..fa5248f3 --- /dev/null +++ b/docs/sklearn_to_astartes.rst @@ -0,0 +1,180 @@ + +Transitioning from ``sklearn`` to ``astartes`` +====================================================== + +Step 1. Installation +-------------------- + +``astartes`` has been designed to rely on (1) as few packages as possible and (2) packages which are already likely to be installed in a Machine Learning (ML) Python workflow (i.e. Numpy and Sklearn). Because of this, ``astartes`` should be compatible with your *existing* workflow such as a conda environment. + +To install ``astartes`` for general ML use (the sampling of arbitrary vectors): **\ ``pip install astartes``\ ** + +For users in cheminformatics, ``astartes`` has an optional add-on that includes featurization as part of the sampling. To install, type **\ ``pip install 'astartes[molecules]'``\ **. With this extra install, ``astartes`` uses `\ ``AIMSim`` `_ to encode SMILES strings as feature vectors. The SMILES strings are parsed into molecular graphs using RDKit and then sampled with a single function call: ``train_test_split_molecules``. + + +* If your workflow already has a featurization scheme in place (i.e. you already have a vector representation of your chemical of interest), you can directly use ``train_test_split`` (though we invite you to explore the many molecular descriptors made available through AIMSim). + +Step 2. Changing the ``import`` Statement +--------------------------------------------- + +In one of the first few lines of your Python script, you have the line ``from sklearn.model_selection import train_test_split``. To switch to using ``astartes`` change this line to ``from astartes import train_test_split``. + +That's it! You are now using ``astartes``. + +If you were just calling ``train_test_split(X, y)``\ , your script should now work in the exact same way as ``sklearn`` with no changes required. + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + random_state=42, + ) + +*becomes* + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + random_state=42, + ) + +But we encourage you to try one of our many other samplers (see below)! + +Step 3. Specifying an Algorithmic Sampler +----------------------------------------- + +By default (for interoperability), ``astartes`` will use a random sampler to produce train/test splits - but the real value of ``astartes`` is in the algorithmic sampling algorithms it implements. Check out the `README for a complete list of available algorithms `_ and how to call and customize them. + +If you existing call to ``train_test_split`` looks like this: + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + ) + +and you want to try out using Kennard-Stone sampling, switch it to this: + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + sampler="kennard_stone", + ) + +That's it! + +Step 4. Passing Keyword Arguments +--------------------------------- + +All of the arguments to the ``sklearn``\ 's ``train_test_split`` can still be passed to ``astartes``\ ' ``train_test_split``\ : + +.. code-block:: python + + X_train, X_test, y_train, y_test, labels_train, labels_test = train_test_split( + X, + y, + labels, + train_size = 0.75, + test_size = 0.25, + sampler = "kmeans", + hopts = {"n_clusters": 4}, + ) + +Some samplers have tunable hyperparameters that allow you to more finely control their behavior. To do this with Sphere Exclusion, for example, switch your call to this: + +.. code-block:: python + + X_train, X_test, y_train, y_test = train_test_split( + X, + y, + sampler="sphere_exclusion", + hopts={"distance_cutoff":0.15}, + ) + +Step 5. Useful ``astartes`` Features +---------------------------------------- + +``return_indices``\ : Improve Code Clarity +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are circumstances where the indices of the train/test data can be useful (for example, if ``y`` or ``labels`` are large, memory-intense objects), and there is no way to directly return these indices in ``sklearn``. ``astartes`` will return the sampling splits themselves by default, but it can also return the indices for the user to manipulate according to their needs: + +.. code-block:: python + + X_train, X_test, y_train, y_test, labels_train, labels_test = train_test_split( + X, + y, + labels, + return_indices = False, + ) + +*could instead be* + +.. code-block:: python + + X_train, X_test, y_train, y_test, labels_train, labels_test, indices_train, indices_test = train_test_split( + X, + y, + labels, + return_indices = True, + ) + +If ``y`` or ``labels`` were large, memory-intense objects it could be beneficial to *not* pass them in to ``train_test_split`` and instead separate the existing lists later using the returned indices. + +``train_val_test_split``\ : More Rigorous ML +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Behind the scenes, ``train_test_split`` is actually just a one-line function that calls the real workhorse of ``astartes`` - ``train_val_test_split``\ : + +.. code-block:: python + + def train_test_split( + X: np.array, + ... + return_indices: bool = False, + ): + return train_val_test_split( + X, y, labels, train_size, 0, test_size, sampler, hopts, return_indices + ) + +The function call to ``train_val_test_split`` is identical to ``train_test_split`` and supports all the same samplers and hyperparameters, except for one additional keyword argument ``val_size``\ : + +.. code-block:: python + + def train_val_test_split( + X: np.array, + y: np.array = None, + labels: np.array = None, + train_size: float = 0.8, + val_size: float = 0.1, + test_size: float = 0.1, + sampler: str = "random", + hopts: dict = {}, + return_indices: bool = False, + ): + +When called, this will return *three* arrays from ``X``\ , ``y``\ , and ``labels`` (or three arrays of indices, if ``return_indices=True``\ ) rather than the usual two, according to the values given for ``train_size``\ , ``val_size``\ , and ``test_size`` in the function call. + +.. code-block:: python + + X_train, X_val, X_test, y_train, y_val, y_test = train_val_test_split( + X, + y, + train_size: float = 0.8, + val_size: float = 0.1, + test_size: float = 0.1, + ) + +For truly rigorous ML modeling, the validation set should be used for hyperparameter tuning and the test set held out until the *very final* change has been made to the model to get a true sense of its performance. For better or for worse, this is *not* the current standard for ML modeling, but the authors believe it should be. + +Custom Warnings: ``ImperfectSplittingWarning`` and ``NormalizationWarning`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the event that your requested train/validation/test split is not mathematically possible given the dimensions of the input data (i.e. you request 50/25/25 but have 101 data points), ``astartes`` will warn you during runtime that it has occurred. ``sklearn`` simply moves on quietly, and while this is fine *most* of the time, the authors felt it prudent to warn the user. +When entering a train/validation/test split, ``astartes`` will check that it is normalized and make it so if not, warning the user during runtime. This will hopefully help prevent head-scratching hours of debugging. diff --git a/docs/test.doctree b/docs/test.doctree new file mode 100644 index 0000000000000000000000000000000000000000..5b93bc87f02701f3ae1319973057f7df69749cf9 GIT binary patch literal 3553 zcmb7H-)kht5!RiwE3H<$E1i8Na3|-CaV%p?>wq7E10i7W%VB}zIB#a?o$1}~>`eE# zf1FkihB)A0LBAaC1HTyj_v8=o-{Y^lXJ&sK7aYODbai!gb=6m2mHyRx@ylp0{<(>+ z85gT7QWQcKRC{++$lO*`82^KR?_2+kzi;DWP;x>2wVe@nOpH-{W^qw`%|0)5@cb|@iPjL}yC+DMzK#l8 zuNO1;rRY59Sa)d1B5Zj!VUO4ed(8IPx%=ak$%;;u6@seija17i(S|5oxBh^WdKzAO zr8NA0^XYv%W5X2Qb$m`+fg65dXH86W3d$SXvL+Ppmi-6BG1ttd9qk}}5j@Mf7CMK@E{?7iwD_Q)NCmmW9|7uRkQpFg)EqJxzFKfVW>0Gc2iL`^HW!IHWYF7nbAbk56Ui+#?%U|&*q zRFPFdYs38017wrb5q8M^qLed#=lYBn1yFkDMvaM1a3pLsqly;(>7F}|pwv>7x6nNX z*w>DSuzkYLW4I0x?Z58E81G6Ey1Y@OuBq~5H|&4Gxs9+RO|(ms8|sZrlQwI+;*BI8 zud&x9@qZv`@|i4bNuT6W7(A;((@XL-qRjt?sINB=H36dbT#t)_u3m=It01$56n9V) zu2A|_bo|dx5}1Z*c^Ox%e{DPox%oGu(KwJQU>({E_S{XHQ{C%n7vW}W9T>7%D!Wm} z!`7A)EnT*xwa(f$nZ0CiehLIBBk)I{|{1Hlw8{f*aWq?prAQo zqzZ*vkdO{i)mRMEH5qI#u{>^;R+U(dP$XF()3A%{dZEH@y?Zd1(g#Du&kwY+}IpwIR4t5C|XNpvXVZd2-c6Lm#|GIH9x^|#F z`gnU|=cGFg4*Uv67l(w4IWW+&!h^sQXrMcKyb9ngB}t_iX2GQgX3+8r)bA}^V3ZnM@-TAn%3{_PlFhZ4X2b*XW)8d-Rfj zp5EKr!=(G^Z<%yMLzrgBCdf1cpg%^^0>6pH6FE=49Fyn0wr$&)b)!w7#g~tA4!DNU zAsR^%_@vcKA>NcEJp>-WtY)(8up3oh-w}4&gDs1L_SSgl!Iu3v(T7I#aMxC|gE10p zmt&3wq`e#FvMd1#yaDa*@RLUV1M>Bq{~Ib7|H6O+@K1*ZR?~$Y>1~OJojAg6*o?A( T_aY$exCp%5P*|8R?Ck1S2*+%5 literal 0 HcmV?d00001 diff --git a/docs/test.functional.doctree b/docs/test.functional.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d816ad1b6d99810c7551a9581715bca0e94a3cd9 GIT binary patch literal 47022 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 literal 0 HcmV?d00001 diff --git a/docs/test.functional.html b/docs/test.functional.html new file mode 100644 index 00000000..9240af02 --- /dev/null +++ b/docs/test.functional.html @@ -0,0 +1,298 @@ + + + + + + + test.functional package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

test.functional package

+
+

Submodules

+
+
+

test.functional.test_astartes module

+
+
+class test.functional.test_astartes.Test_astartes(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of astartes.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_close_mispelling_sampler()
+

Astartes should be helpful in the event of a typo.

+
+ +
+
+test_inconsistent_input_lengths()
+

Different length X, y, and labels should raise an exception at start.

+
+ +
+
+test_insufficient_dataset_test()
+

If the user requests a split that would result in rounding down the size of the +test set to zero, a helpful exception should be raised.

+
+ +
+
+test_insufficient_dataset_train()
+

If the user requests a split that would result in rounding down the size of the +test set to zero, a helpful exception should be raised.

+
+ +
+
+test_insufficient_dataset_val()
+

If the user requests a split that would result in rounding down the size of the +test set to zero, a helpful exception should be raised.

+
+ +
+
+test_not_implemented_sampler()
+

Astartes should suggest checking the docstring.

+
+ +
+
+test_return_indices()
+

Test the ability to return the indices and the values.

+
+ +
+
+test_return_indices_with_validation()
+

Test the ability to return indices in train_val_test_split

+
+ +
+
+test_split_validation()
+

Tests of the input split validation.

+
+ +
+
+test_train_test_split()
+

Funational test of train_test_split with imperfect splitting.

+
+ +
+
+test_train_val_test_split()
+

Split data into training, validation, and test sets.

+
+ +
+
+test_train_val_test_split_extrpolation_shuffling()
+

Split data into training, validation, and test sets with shuffling.

+
+ +
+ +
+
+

test.functional.test_molecules module

+
+
+class test.functional.test_molecules.Test_molecules(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of molecules.

+

Note: daylight_fingerprint is not compatible – inhomogenous arrays +(variable length descriptor)

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_fingerprints()
+

Test using different fingerprints with the molecular featurization.

+
+ +
+
+test_fprint_hopts()
+

Test specifying hyperparameters for the molecular featurization step.

+
+ +
+
+test_maximum_call()
+

Specify ALL the optional hyperparameters!

+
+ +
+
+test_molecules()
+

Try train_test_split molecules with every interpolative sampler.

+
+ +
+
+test_molecules_with_rdkit()
+

Try train_test_split molecules, every sampler, passing rdkit objects.

+
+ +
+
+test_molecules_with_troublesome_smiles()
+

Helpful errors when rdkit graphs can’t be featurized.

+
+ +
+
+test_sampler_hopts()
+

Test ability to pass through sampler hopts with molecules interface, expecting no warnings.

+
+ +
+
+test_validation_split_molecules()
+

Try train_val_test_split_molecule with every extrapolative sampler.

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.functional.rst b/docs/test.functional.rst new file mode 100644 index 00000000..0c1189a2 --- /dev/null +++ b/docs/test.functional.rst @@ -0,0 +1,29 @@ +test.functional package +======================= + +Submodules +---------- + +test.functional.test\_astartes module +------------------------------------- + +.. automodule:: test.functional.test_astartes + :members: + :undoc-members: + :show-inheritance: + +test.functional.test\_molecules module +-------------------------------------- + +.. automodule:: test.functional.test_molecules + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.functional + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/test.html b/docs/test.html new file mode 100644 index 00000000..25fdaddf --- /dev/null +++ b/docs/test.html @@ -0,0 +1,220 @@ + + + + + + + test package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

test package

+
+

Subpackages

+
+ +
+
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.regression.doctree b/docs/test.regression.doctree new file mode 100644 index 0000000000000000000000000000000000000000..60843e06ac529e632e867b8917ac1617ea95d57e GIT binary patch literal 17390 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 + + + + + + test.regression package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

test.regression package

+
+

Submodules

+
+
+

test.regression.test_regression module

+
+
+class test.regression.test_regression.Test_regression(methodName='runTest')
+

Bases: TestCase

+

Test for regression relative to saved reference splits.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_extrapolation_regression()
+

Regression testing of extrapolative methods relative to static results.

+
+ +
+
+test_interpolation_regression()
+

Regression testing of interpolative methods relative to static results.

+
+ +
+
+test_kmeans_regression_sklearn_v12()
+

Regression testing of KMeans in sklearn v1.2 or earlier.

+
+ +
+
+test_kmeans_regression_sklearn_v13()
+

Regression testing of KMeans in sklearn v1.3 or newer.

+
+ +
+
+test_timebased_regression()
+

Regression test TimeBased, which has labels to check as well.

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.regression.rst b/docs/test.regression.rst new file mode 100644 index 00000000..c3cb03bb --- /dev/null +++ b/docs/test.regression.rst @@ -0,0 +1,21 @@ +test.regression package +======================= + +Submodules +---------- + +test.regression.test\_regression module +--------------------------------------- + +.. automodule:: test.regression.test_regression + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.regression + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/test.rst b/docs/test.rst new file mode 100644 index 00000000..9fca9975 --- /dev/null +++ b/docs/test.rst @@ -0,0 +1,20 @@ +test package +============ + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test.functional + test.regression + test.unit + +Module contents +--------------- + +.. automodule:: test + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/test.unit.doctree b/docs/test.unit.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7a06f19eac216a476237c4d6f1146445964bb745 GIT binary patch literal 3589 zcmb7HU2h||74@zy*|IIkcCtZ%U8fraNgOnm@=z2-3KRwMxQNgsMcx8}nxRD29CFH! zwfs;ZeMk`l1omOsyadSa>2K;&4`)U*k~SM81_TT*zb?-`_uT7mdjI*~aIg9cV_R~e zRuh`%O6SbRaFpxJ7fiYMGJg24_|JG128P~R?M=pF*u#p93z-|H;@2^Z(sC!HoizIo zEz6wHs@=|eyw4B6j#qpTdQLdWHm1V4W7bW)67Fe9vm3f(F)ha0gTJv=a^k0!d>d=e z`Xz-QF7op*Ag$wkKlB@aXW>8!#p2A*X*j0N88P>`vU=CP$ZdMVVJ4}yFygzXXihbh+un;NeaGt*mbZl=^aYH(fm0VnOW zee=XvIREyuhknjaYP37J&en!-@}-|Q=-3*bx3+B!9&qO4+L;-DJ3X2I7V+cn0MB>v zdk?=4@cR&N;J>SUzpj__kKjZPP7DxTU6k6Zd?QMA0Qnvst}|!YW(1qL*ImRPhe7*X zK#gb_Q2~543m5Io#L}Xa%-HzvI1A&>UU3UX7EXoAq|ezx$a+8joPWu}Q9)NZD;|79Q8YT;Cd6mdr%Di}s(fZv$;ahqciOCw3#ibRDc+^G58BJKnXi`xyd_ zKhwFF>}jTz!?Rivy<+c(WPTly^ahbeAktpw36-$Qk=LHr4Yd*$f;4fLP|ug}|7*!V}`O=qaGk|x5F(&(jOwidRY(~ioT)yF_T(}2zoOD33D*^Zk7r@9WRN}Tv_S$7 za+;!poW|g!zJ}oJ8w`(|p*IqvArglqaZR(hu9vdzE{2PR)=p{1HYT4v2*XrekhWyC z(58s6j4TADBv7qXv@DK%Tw9oAm4)02$H`jaabvTg(fnCBHLTRe5y_r2fc7vPb1K_m zFPyWL09KAVZ`X@@p_j9{U*fvaEj0>QVTEC|fMtNdWGp=@eiueUmEIAiGM!^p3Q+m}YF>R=W8%Fh^odfHwPqrs^ zc80U`0MN^F;3M&%7>1InrALhh+&RV%p{wBy!!m7h0ug4&c$Fo2pM^ehY=Jid4v~YN z(Ct;^{V<~5Y0{a(Ljgt&b6=FCWgSqh3<7dx6qV_~ab>AEpJLycO3Qq%$*M?vI%BI+ zTShi_Rust`c`mG|`8g)JuyiidLmDp+*V%x~I>low_+O;xM)(bP zuC$*_r!d<|dFQxR6K$5$7#^jSl>=Bw97E+qx}hEPA#vHj(K%8mPX+cUT!N4VX>+rE0I?80hQfJf@06n}!o`wH z{6O9VsT1!{ZGm2h{KF%uEr5EX8rMT2bw=y59xgLZ;ST~|CmT?%AjIw)U*d|?a#qE< z5dl-zL)3MPDjL5-E&2QC!QLJ^ z-@pEn&Nmf=X{wP^f{;Q{30VCJB9}x?EuZSeMv+H5`e0qk{oIG)Cgmy&hM53y6Ntd2 zwj^a)udBh{wAAYm0#LM=YuU26TKeXWv0XjbI&rYRwc2#Cb$-?Br;_w&_pD|HO(t|N zLvsys$8eHqDM1gs0fq1I)5iW1k^44&fgHv^H&6roJ7U4w`odQJw#+B3xgy?4)98Ze T%fz|kJSlV|W~tNg^U41Kh3I+g literal 0 HcmV?d00001 diff --git a/docs/test.unit.html b/docs/test.unit.html new file mode 100644 index 00000000..18e5a855 --- /dev/null +++ b/docs/test.unit.html @@ -0,0 +1,202 @@ + + + + + + + test.unit package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.unit.rst b/docs/test.unit.rst new file mode 100644 index 00000000..d11aa2eb --- /dev/null +++ b/docs/test.unit.rst @@ -0,0 +1,19 @@ +test.unit package +================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test.unit.samplers + test.unit.utils + +Module contents +--------------- + +.. automodule:: test.unit + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/test.unit.samplers.doctree b/docs/test.unit.samplers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ddb28cc862d428b7c720040bb09c4390ff4f421b GIT binary patch literal 3710 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 GyZ%3dO#7k$ literal 0 HcmV?d00001 diff --git a/docs/test.unit.samplers.extrapolative.html b/docs/test.unit.samplers.extrapolative.html new file mode 100644 index 00000000..daf642b4 --- /dev/null +++ b/docs/test.unit.samplers.extrapolative.html @@ -0,0 +1,365 @@ + + + + + + + test.unit.samplers.extrapolative package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

test.unit.samplers.extrapolative package

+
+

Submodules

+
+
+

test.unit.samplers.extrapolative.test_DBSCAN module

+
+
+class test.unit.samplers.extrapolative.test_DBSCAN.Test_DBSCAN(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of dbscan.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_dbscan()
+

Directly instantiate and test DBSCAN.

+
+ +
+
+test_dbscan_sampling()
+

Use dbscan in the train_test_split and verify results.

+
+ +
+ +
+
+

test.unit.samplers.extrapolative.test_Scaffold module

+
+
+class test.unit.samplers.extrapolative.test_Scaffold.Test_scaffold(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of Scaffold.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_include_chirality()
+

Include chirality in scaffold calculation

+
+ +
+
+test_incorrect_input()
+

Calling with something other than SMILES should raise TypeError

+
+ +
+
+test_mol_from_inchi()
+

Ability to load data from InChi inputs

+
+ +
+
+test_no_scaffold_found_warning()
+

Molecules that cannot be scaffolded should raise a warning

+
+ +
+
+test_remove_atom_map()
+

Scaffolds should not include atom map numbers

+
+ +
+
+test_scaffold()
+

Directly instantiate and test Scaffold.

+
+ +
+
+test_scaffold_sampling()
+

Use Scaffold in the train_test_split and verify results.

+
+ +
+ +
+
+

test.unit.samplers.extrapolative.test_kmeans module

+
+
+class test.unit.samplers.extrapolative.test_kmeans.Test_kmeans(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of kmeans.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_kmeans()
+

Directly instantiate and test KMeans.

+
+ +
+
+test_kmeans_sampling_v12()
+

Use kmeans in the train_test_split and verify results.

+
+ +
+
+test_kmeans_sampling_v13()
+

Use kmeans in the train_test_split and verify results.

+
+ +
+ +
+
+

test.unit.samplers.extrapolative.test_optisim module

+
+
+class test.unit.samplers.extrapolative.test_optisim.Test_optisim(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of optisim.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_optisim()
+

Directly instantiate and test OptiSim

+
+ +
+
+test_optisim_sampling()
+

Use kmeans in the train_test_split and verify results.

+
+ +
+ +
+
+

test.unit.samplers.extrapolative.test_sphere_exclusion module

+
+
+class test.unit.samplers.extrapolative.test_sphere_exclusion.Test_sphere_exclusion(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of sphere_exclusion.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_sphereexclusion()
+

Directly instantiate and test KMeans.

+
+ +
+
+test_sphereexclusion_sampling()
+

Use kmeans in the train_test_split and verify results.

+
+ +
+ +
+
+

test.unit.samplers.extrapolative.test_time_based module

+
+
+class test.unit.samplers.extrapolative.test_time_based.Test_time_based(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of TimeBased.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_incorrect_input()
+

Specifying labels as neither date nor datetime object should raise TypeError

+
+ +
+
+test_mising_labels()
+

Not specifying labels should raise ValueError

+
+ +
+
+test_time_based_date()
+

Directly instantiate and test TimeBased.

+
+ +
+
+test_time_based_datetime()
+

Directly instantiate and test TimeBased.

+
+ +
+
+test_time_based_sampling()
+

Use time_based in the train_test_split and verify results.

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.unit.samplers.extrapolative.rst b/docs/test.unit.samplers.extrapolative.rst new file mode 100644 index 00000000..cd6b17ef --- /dev/null +++ b/docs/test.unit.samplers.extrapolative.rst @@ -0,0 +1,61 @@ +test.unit.samplers.extrapolative package +======================================== + +Submodules +---------- + +test.unit.samplers.extrapolative.test\_DBSCAN module +---------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_DBSCAN + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_Scaffold module +------------------------------------------------------ + +.. automodule:: test.unit.samplers.extrapolative.test_Scaffold + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_kmeans module +---------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_kmeans + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_optisim module +----------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_optisim + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_sphere\_exclusion module +--------------------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_sphere_exclusion + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.extrapolative.test\_time\_based module +--------------------------------------------------------- + +.. automodule:: test.unit.samplers.extrapolative.test_time_based + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.unit.samplers.extrapolative + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/test.unit.samplers.html b/docs/test.unit.samplers.html new file mode 100644 index 00000000..dcf7bb6e --- /dev/null +++ b/docs/test.unit.samplers.html @@ -0,0 +1,249 @@ + + + + + + + test.unit.samplers package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

test.unit.samplers package

+
+

Subpackages

+
+ +
+
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.unit.samplers.interpolative.doctree b/docs/test.unit.samplers.interpolative.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7d79821882eddee7b4f85076328714e953aa8e34 GIT binary patch literal 35450 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 bXZE^&v)yeGt}Rn+vZqA>nT%b8x0?Sy64SJ+ literal 0 HcmV?d00001 diff --git a/docs/test.unit.samplers.interpolative.html b/docs/test.unit.samplers.interpolative.html new file mode 100644 index 00000000..6660840a --- /dev/null +++ b/docs/test.unit.samplers.interpolative.html @@ -0,0 +1,245 @@ + + + + + + + test.unit.samplers.interpolative package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

test.unit.samplers.interpolative package

+
+

Submodules

+
+
+

test.unit.samplers.interpolative.test_kennard_stone module

+
+
+class test.unit.samplers.interpolative.test_kennard_stone.Test_kennard_stone(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of kennard_stone.

+
+
+classmethod setUpClass()
+

Save re-used arrays as class attributes.

+
+ +
+
+test_kennard_stone()
+

Directly instantiate and test KennardStone.

+
+ +
+
+test_kennard_stone_sample()
+

Use kennard stone in tts and verify results

+
+ +
+
+test_kennard_stone_sample_no_warning()
+

Use kennard stone with a mathematically possible split requested

+
+ +
+ +
+
+

test.unit.samplers.interpolative.test_random module

+
+
+class test.unit.samplers.interpolative.test_random.Test_random(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of Random.

+
+
+classmethod setUpClass()
+

Save re-used arrays as class attributes.

+
+ +
+
+test_random()
+

Directly instantiate and test random.

+
+ +
+
+test_random_sample()
+

Use kennard stone in tts and verify results

+
+ +
+
+test_random_sample_no_warning()
+

Use random with a mathematically possible split requested

+
+ +
+ +
+
+

test.unit.samplers.interpolative.test_spxy module

+
+
+class test.unit.samplers.interpolative.test_spxy.Test_SPXY(methodName='runTest')
+

Bases: TestCase

+

Test the various functionalities of SPXY.

+
+
+classmethod setUpClass()
+

Convenience attributes for later tests.

+
+ +
+
+test_missing_y()
+

SPXY requires a y array and should complain when one is not provided.

+
+ +
+
+test_spxy()
+

Directly instantiate and test SPXY

+
+ +
+
+test_spxy_sampling()
+

Use spxy in the train_test_split and verify results.

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.unit.samplers.interpolative.rst b/docs/test.unit.samplers.interpolative.rst new file mode 100644 index 00000000..812af5a9 --- /dev/null +++ b/docs/test.unit.samplers.interpolative.rst @@ -0,0 +1,37 @@ +test.unit.samplers.interpolative package +======================================== + +Submodules +---------- + +test.unit.samplers.interpolative.test\_kennard\_stone module +------------------------------------------------------------ + +.. automodule:: test.unit.samplers.interpolative.test_kennard_stone + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.interpolative.test\_random module +---------------------------------------------------- + +.. automodule:: test.unit.samplers.interpolative.test_random + :members: + :undoc-members: + :show-inheritance: + +test.unit.samplers.interpolative.test\_spxy module +-------------------------------------------------- + +.. automodule:: test.unit.samplers.interpolative.test_spxy + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.unit.samplers.interpolative + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/test.unit.samplers.rst b/docs/test.unit.samplers.rst new file mode 100644 index 00000000..dc112797 --- /dev/null +++ b/docs/test.unit.samplers.rst @@ -0,0 +1,19 @@ +test.unit.samplers package +========================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test.unit.samplers.extrapolative + test.unit.samplers.interpolative + +Module contents +--------------- + +.. automodule:: test.unit.samplers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/test.unit.utils.doctree b/docs/test.unit.utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2e47db445659e022140be3d0b5101cb4d364d5b4 GIT binary patch literal 27782 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 + + + + + + test.unit.utils package — astartes astartes.__version__ documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

test.unit.utils package

+
+

Submodules

+
+
+

test.unit.utils.test_convert_to_array module

+
+
+class test.unit.utils.test_convert_to_array.Test_convert_to_array(methodName='runTest')
+

Bases: TestCase

+

Test array type handling.

+
+
+test_bad_type_cast()
+

Raise error when casting arrays that do not contain supported types.

+
+ +
+
+test_convertable_input()
+

Raise warning when casting.

+
+ +
+
+test_panda_handla()
+

Splitting Dataframes and series should return them as such.

+
+ +
+
+test_unconvertable_input()
+

Raise error when casting fails.

+
+ +
+ +
+
+

test.unit.utils.test_sampler_factory module

+
+
+class test.unit.utils.test_sampler_factory.Test_sampler_factory(methodName='runTest')
+

Bases: TestCase

+

Test SamplerFactory functions on all samplers.

+
+
+classmethod setUpClass()
+

Save re-used arrays as class attributes.

+
+ +
+
+test_train_test_split()
+

Call sampler factory on all inputs.

+
+ +
+ +
+
+

test.unit.utils.test_utils module

+
+
+class test.unit.utils.test_utils.Test_utils(methodName='runTest')
+

Bases: TestCase

+

Test functions within utils.py.

+
+
+classmethod setUpClass()
+

Save re-used arrays as class attributes.

+
+ +
+
+test_generate_regression_results_dict()
+

Generate results dictionary for simple regression task.

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/test.unit.utils.rst b/docs/test.unit.utils.rst new file mode 100644 index 00000000..d4b96cf4 --- /dev/null +++ b/docs/test.unit.utils.rst @@ -0,0 +1,37 @@ +test.unit.utils package +======================= + +Submodules +---------- + +test.unit.utils.test\_convert\_to\_array module +----------------------------------------------- + +.. automodule:: test.unit.utils.test_convert_to_array + :members: + :undoc-members: + :show-inheritance: + +test.unit.utils.test\_sampler\_factory module +--------------------------------------------- + +.. automodule:: test.unit.utils.test_sampler_factory + :members: + :undoc-members: + :show-inheritance: + +test.unit.utils.test\_utils module +---------------------------------- + +.. automodule:: test.unit.utils.test_utils + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test.unit.utils + :members: + :undoc-members: + :show-inheritance: