├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── stale.yml ├── .gitignore ├── .gitmodules ├── .pylintrc ├── .travis.yml ├── AUTHORS ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── azure-pipelines.yml ├── conftest.py ├── devtools ├── azure-pipelines-linux.yml ├── azure-pipelines-osx.yml ├── azure-pipelines-win.yml ├── checkout.yml ├── ci │ └── travis │ │ ├── install_miniconda.sh │ │ └── make_docs.sh ├── conda-recipe │ ├── matplotlibrc │ ├── meta.yaml │ └── run_test.py ├── conda-setup+build.yml ├── doc-recipe │ ├── README.txt │ ├── build.sh │ └── meta.yaml └── test-results.yml ├── doc ├── .gitignore ├── Makefile ├── README.rst ├── requirements-build-doc.txt └── source │ ├── CHANGELOG.rst │ ├── Configuration.rst │ ├── DEVELOPMENT.rst │ ├── INSTALL.rst │ ├── _static │ ├── custom.css │ ├── emma-logo.png │ ├── favicon.ico │ └── pyemma_paper_doi.svg │ ├── api │ ├── coordinates.clustering.rst │ ├── coordinates.data.rst │ ├── coordinates.pipelines.rst │ ├── coordinates.transform.rst │ ├── index.rst │ ├── index_coor.rst │ ├── index_msm.rst │ ├── index_plots.rst │ ├── index_serialization.rst │ └── index_thermo.rst │ ├── conf.py │ ├── index.rst │ ├── ipython.rst │ ├── legal.rst │ └── tutorial.rst ├── install_miniconda+pyemma.sh ├── pyemma ├── __init__.py ├── _base │ ├── __init__.py │ ├── estimator.py │ ├── loggable.py │ ├── model.py │ ├── parallel.py │ ├── progress │ │ ├── __init__.py │ │ ├── reporter │ │ │ └── __init__.py │ │ └── test_progress.py │ ├── serialization │ │ ├── __init__.py │ │ ├── cli.py │ │ ├── h5file.py │ │ ├── mdtraj_helpers.py │ │ ├── pickle_extensions.py │ │ ├── serialization.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── _test_classes.py │ │ │ ├── test_cli.py │ │ │ ├── test_serialization.py │ │ │ └── test_topology.py │ │ └── util.py │ └── tests │ │ ├── __init__.py │ │ └── test_estimator.py ├── _ext │ ├── __init__.py │ ├── orderedset │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── __init__.py │ │ └── _orderedset.pyx │ ├── sklearn │ │ ├── __init__.py │ │ ├── base.py │ │ └── parameter_search.py │ └── variational │ │ ├── __init__.py │ │ ├── estimators │ │ ├── __init__.py │ │ ├── covar_c │ │ │ ├── CMakeLists.txt │ │ │ ├── __init__.py │ │ │ ├── covartools.cpp │ │ │ ├── covartools.py │ │ │ └── covartools_cpp.h │ │ ├── moments.py │ │ ├── running_moments.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ ├── benchmark_moments.py │ │ │ ├── test_moments.py │ │ │ └── test_running_moments.py │ │ ├── solvers │ │ ├── __init__.py │ │ ├── direct.py │ │ ├── eig_qr │ │ │ ├── .gitignore │ │ │ ├── __init__.py │ │ │ └── eig_qr.pyx │ │ └── tests │ │ │ ├── __init__.py │ │ │ └── test_direct.py │ │ └── util.py ├── _version.py ├── coordinates │ ├── __init__.py │ ├── acf.py │ ├── api.py │ ├── clustering │ │ ├── __init__.py │ │ ├── assign.py │ │ ├── interface.py │ │ ├── kmeans.py │ │ ├── regspace.py │ │ ├── src │ │ │ └── clustering_module.cpp │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── test_assign.py │ │ │ ├── test_cluster.py │ │ │ ├── test_cluster_samples.py │ │ │ ├── test_kmeans.py │ │ │ ├── test_mini_batch_kmeans.py │ │ │ ├── test_regspace.py │ │ │ ├── test_uniform_time.py │ │ │ └── util.py │ │ └── uniform_time.py │ ├── data │ │ ├── __init__.py │ │ ├── _base │ │ │ ├── __init__.py │ │ │ ├── _in_memory_mixin.py │ │ │ ├── datasource.py │ │ │ ├── iterable.py │ │ │ ├── random_accessible.py │ │ │ ├── streaming_estimator.py │ │ │ └── transformer.py │ │ ├── data_in_memory.py │ │ ├── feature_reader.py │ │ ├── featurization │ │ │ ├── __init__.py │ │ │ ├── _base.py │ │ │ ├── angles.py │ │ │ ├── distances.py │ │ │ ├── featurizer.py │ │ │ ├── misc.py │ │ │ └── util.py │ │ ├── fragmented_trajectory_reader.py │ │ ├── h5_reader.py │ │ ├── numpy_filereader.py │ │ ├── py_csv_reader.py │ │ ├── sources_merger.py │ │ └── util │ │ │ ├── __init__.py │ │ │ ├── frames_from_file.py │ │ │ ├── reader_utils.py │ │ │ ├── traj_info_backends.py │ │ │ └── traj_info_cache.py │ ├── estimation │ │ ├── __init__.py │ │ ├── covariance.py │ │ └── koopman.py │ ├── pipelines.py │ ├── tests │ │ ├── __init__.py │ │ ├── data │ │ │ ├── bpti_001-033.xtc │ │ │ ├── bpti_034-066.xtc │ │ │ ├── bpti_067-100.xtc │ │ │ ├── bpti_ca.pdb │ │ │ ├── bpti_mini.binpos │ │ │ ├── bpti_mini.dcd │ │ │ ├── bpti_mini.h5 │ │ │ ├── bpti_mini.lh5 │ │ │ ├── bpti_mini.nc │ │ │ ├── bpti_mini.netcdf │ │ │ ├── bpti_mini.trr │ │ │ ├── bpti_mini.xtc │ │ │ ├── opsin_Ca_1_frame.pdb.gz │ │ │ ├── opsin_aa_1_frame.pdb.gz │ │ │ ├── test.pdb │ │ │ └── test_data_koopman.npz │ │ ├── test_acf.py │ │ ├── test_api_load.py │ │ ├── test_api_source.py │ │ ├── test_coordinates_iterator.py │ │ ├── test_covar_estimator.py │ │ ├── test_csvreader.py │ │ ├── test_datainmemory.py │ │ ├── test_discretizer.py │ │ ├── test_eq_covar_estimator.py │ │ ├── test_featurereader.py │ │ ├── test_featurereader_and_tica.py │ │ ├── test_featurereader_and_tica_projection.py │ │ ├── test_featurizer.py │ │ ├── test_fragmented_trajectory.py │ │ ├── test_frames_from_file.py │ │ ├── test_h5reader.py │ │ ├── test_koopman_estimator.py │ │ ├── test_numpyfilereader.py │ │ ├── test_nystroem_tica.py │ │ ├── test_pca.py │ │ ├── test_pipeline.py │ │ ├── test_random_access_stride.py │ │ ├── test_readers.py │ │ ├── test_save_traj.py │ │ ├── test_save_trajs.py │ │ ├── test_serialization.py │ │ ├── test_source.py │ │ ├── test_sources_merger.py │ │ ├── test_streaming_transformer.py │ │ ├── test_stride.py │ │ ├── test_tica.py │ │ ├── test_traj_info_cache.py │ │ ├── test_vamp.py │ │ └── util.py │ ├── transform │ │ ├── __init__.py │ │ ├── _tica_base.py │ │ ├── nystroem_tica.py │ │ ├── pca.py │ │ ├── tica.py │ │ └── vamp.py │ └── util │ │ ├── __init__.py │ │ ├── patches.py │ │ └── stat.py ├── datasets │ ├── __init__.py │ ├── api.py │ ├── double_well_discrete.py │ ├── double_well_thermo.py │ ├── potentials.py │ └── tests │ │ ├── __init__.py │ │ └── test_datasets.py ├── logging.yml ├── msm │ ├── __init__.py │ ├── api.py │ ├── estimators │ │ ├── _OOM_MSM.py │ │ ├── __init__.py │ │ ├── _dtraj_stats.py │ │ ├── _msm_estimator_base.py │ │ ├── augmented_msm.py │ │ ├── bayesian_hmsm.py │ │ ├── bayesian_msm.py │ │ ├── implied_timescales.py │ │ ├── lagged_model_validators.py │ │ ├── maximum_likelihood_hmsm.py │ │ ├── maximum_likelihood_msm.py │ │ └── oom_reweighted_msm.py │ ├── models │ │ ├── __init__.py │ │ ├── hmsm.py │ │ ├── hmsm_sampled.py │ │ ├── msm.py │ │ ├── msm_sampled.py │ │ ├── pcca.py │ │ └── reactive_flux.py │ ├── tests │ │ ├── __init__.py │ │ ├── birth_death_chain.py │ │ ├── data │ │ │ ├── TestData_ITS_OOM.npz │ │ │ └── TestData_OOM_MSM.npz │ │ ├── test_amm.py │ │ ├── test_bayesian_hmsm.py │ │ ├── test_bayesian_msm.py │ │ ├── test_cktest.py │ │ ├── test_cmsm.py │ │ ├── test_dtraj_stats.py │ │ ├── test_estimator.py │ │ ├── test_hmsm.py │ │ ├── test_its.py │ │ ├── test_its_oom.py │ │ ├── test_msm.py │ │ ├── test_msm_serialization.py │ │ ├── test_oom_msm.py │ │ ├── test_reactive_flux.py │ │ ├── test_subset.py │ │ └── test_tpt.py │ └── util │ │ ├── __init__.py │ │ └── subset.py ├── plots │ ├── __init__.py │ ├── _ext │ │ ├── __init__.py │ │ └── fruchterman_reingold.py │ ├── markovtests.py │ ├── networks.py │ ├── plots1d.py │ ├── plots2d.py │ ├── tests │ │ ├── __init__.py │ │ ├── test_its.py │ │ ├── test_markovtests.py │ │ ├── test_networks.py │ │ ├── test_plots1d.py │ │ └── test_plots2d.py │ ├── thermoplots.py │ └── timescales.py ├── pyemma.cfg ├── thermo │ ├── __init__.py │ ├── api.py │ ├── estimators │ │ ├── DTRAM_estimator.py │ │ ├── MBAR_estimator.py │ │ ├── TRAM_estimator.py │ │ ├── WHAM_estimator.py │ │ ├── __init__.py │ │ ├── _base.py │ │ └── _callback.py │ ├── extensions │ │ ├── .gitignore │ │ ├── __init__.py │ │ ├── bar │ │ │ ├── _bar.c │ │ │ ├── _bar.h │ │ │ └── bar.pyx │ │ ├── callback.py │ │ ├── cset.py │ │ ├── dtram │ │ │ ├── _dtram.c │ │ │ ├── _dtram.h │ │ │ └── dtram.pyx │ │ ├── mbar │ │ │ ├── _mbar.c │ │ │ ├── _mbar.h │ │ │ └── mbar.pyx │ │ ├── mbar_direct │ │ │ ├── _mbar_direct.c │ │ │ ├── _mbar_direct.h │ │ │ └── mbar_direct.pyx │ │ ├── tram │ │ │ ├── _tram.c │ │ │ ├── _tram.h │ │ │ └── tram.pyx │ │ ├── tram_direct │ │ │ ├── _tram_direct.c │ │ │ ├── _tram_direct.h │ │ │ └── tram_direct.pyx │ │ ├── trammbar │ │ │ └── trammbar.pyx │ │ ├── trammbar_direct │ │ │ └── trammbar_direct.pyx │ │ ├── util │ │ │ ├── _util.c │ │ │ ├── _util.h │ │ │ └── util.pyx │ │ └── wham │ │ │ ├── _wham.c │ │ │ ├── _wham.h │ │ │ └── wham.pyx │ ├── models │ │ ├── __init__.py │ │ ├── memm.py │ │ ├── multi_therm.py │ │ └── stationary.py │ ├── tests │ │ ├── test_DTRAM.py │ │ ├── test_TRAM.py │ │ ├── test_api.py │ │ ├── test_thermo_msm.py │ │ └── test_util.py │ └── util │ │ ├── __init__.py │ │ └── util.py └── util │ ├── .gitignore │ ├── __init__.py │ ├── _config.py │ ├── annotators.py │ ├── contexts.py │ ├── debug.py │ ├── discrete_trajectories.py │ ├── exceptions.py │ ├── files.py │ ├── indices.py │ ├── linalg.py │ ├── log.py │ ├── metrics.py │ ├── numeric.py │ ├── reflection.py │ ├── statistics.py │ ├── testing_tools.py │ ├── tests │ ├── __init__.py │ ├── data │ │ ├── dtraj.dat │ │ └── dtraj.npy │ ├── statistics_test.py │ ├── test_config.py │ ├── test_discrete_trajectories.py │ ├── test_log.py │ ├── test_shortcut.py │ └── test_units.py │ ├── types.py │ └── units.py ├── pyproject.toml ├── setup.cfg ├── setup.py ├── setup_util.py └── versioneer.py /.gitattributes: -------------------------------------------------------------------------------- 1 | pyemma/_version.py export-subst 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks for submitting an issue! 2 | 3 | Here's a quick checklist in what to include: 4 | 5 | - [ ] Include a detailed description of the bug or suggestion 6 | - [ ] `pip list` or `conda list` of the environment you are using (please attach a txt file to the issue). 7 | - [ ] PyEMMA version and operating system versions 8 | - [ ] Minimal example if possible, a Python script, zipped input data (if not too large) 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks for submitting a PR, your contribution is really appreciated! 2 | 3 | Here's a quick checklist that should be present in PRs: 4 | 5 | - [ ] Make sure to include one or more tests for your change 6 | - [ ] Add yourself to `AUTHORS` 7 | - [ ] Add a new entry to the `doc/source/CHANGELOG` (choose any open position to avoid merge conflicts with other PRs). 8 | Decide whether your change is a fix or a new feature. 9 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 180 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 30 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - bug 9 | - feature-request 10 | - security 11 | # Label to use when marking an issue as stale 12 | staleLabel: wontfix 13 | # Comment to post when marking an issue as stale. Set to `false` to disable 14 | markComment: > 15 | This issue has been automatically marked as stale because it has not had 16 | recent activity. It will be closed if no further activity occurs. Thank you 17 | for your contributions. 18 | # Comment to post when closing a stale issue. Set to `false` to disable 19 | closeComment: false 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.orig 2 | *.bak 3 | build* 4 | *.log 5 | *.egg 6 | .eggs 7 | /.settings 8 | /.tox 9 | *.pyc 10 | *.pyd 11 | *.egg-info 12 | *.so 13 | /temp 14 | /tmp 15 | /target 16 | __pycache__ 17 | /pylint/pylint_*.txt 18 | /dist 19 | .externalToolBuilders 20 | 21 | # ignore untitled ipython notebooks 22 | Untitled*.ipynb 23 | 24 | # generated from MANIFEST.in 25 | MANIFEST 26 | doc/source/api/generated/ 27 | .ipynb_checkpoints 28 | 29 | # project files 30 | .idea 31 | 32 | # generated from setup.py 33 | pyemma/_extensions.json 34 | pyemma/setup.cfg 35 | 36 | # generated c-files: 37 | pyemma/_ext/variational/estimators/covar_c/covartools.c 38 | 39 | # pytest 40 | .pytest_cache 41 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "doc/source/legacy-notebooks"] 2 | path = doc/source/legacy-notebooks 3 | url = https://github.com/markovmodel/PyEMMA_IPython.git 4 | [submodule "doc/source/tutorials"] 5 | path = doc/source/tutorials 6 | url = https://github.com/markovmodel/pyemma_tutorials 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | git: 3 | submodules: false 4 | depth: 500 5 | os: 6 | - osx 7 | - linux 8 | 9 | sudo: false 10 | 11 | env: 12 | global: 13 | - MINICONDA_DIR="$HOME/miniconda" 14 | - PYTHONHASHSEED=0 15 | - OMP_NUM_THREADS=2 16 | - PYEMMA_NJOBS=1 17 | - MACOSX_DEPLOYMENT_TARGET=10.9 18 | - CONDA_BUILD=YES 19 | matrix: 20 | - CONDA_PY='3.6' 21 | CONDA_NPY='1.16' 22 | - CONDA_PY='3.7' 23 | CONDA_NPY='1.17' 24 | - CONDA_PY='3.8' 25 | CONDA_NPY='1.17' 26 | 27 | matrix: 28 | exclude: # test only 3.8 on osx. 29 | - env: CONDA_PY=3.6 30 | os: osx 31 | include: # test pip install 32 | - env: CONDA_PY=3.7 CONDA_BUILD=NO python="3.7" 33 | os: linux 34 | dist: bionic # You’ll need to add dist: bionic to use Python 3.7 and higher. 35 | language: python 36 | sudo: true 37 | 38 | 39 | before_install: 40 | - if [[ ${CONDA_BUILD} = YES ]]; then 41 | source devtools/ci/travis/install_miniconda.sh; 42 | fi 43 | 44 | script: 45 | - if [[ ${CONDA_BUILD} = YES ]]; then 46 | conda build -q devtools/conda-recipe -c conda-forge; 47 | else 48 | pip install pip -U; 49 | pip install . ; 50 | rm -r pyemma; 51 | pip install pytest tables; 52 | pytest --pyargs pyemma; 53 | fi 54 | 55 | after_script: 56 | - if [[ ${CONDA_BUILD} = YES ]]; then bash <(curl -s https://codecov.io/bash) -f $HOME/coverage.xml -e CONDA_PY; fi 57 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Main Authors 2 | ============ 3 | Benjamin Trendelkamp-Schroer 4 | Christoph Wehmeyer 5 | Fabian Paul 6 | Frank Noe 7 | Guillermo Pérez-Hernández 8 | Martin K. Scherer 9 | Moritz Hoffmann 10 | Jan-Hendrik Prinz 11 | 12 | 13 | 14 | Contributors 15 | ============ 16 | Alexandra La Fleur 17 | Antonia Mey 18 | Ariel Rokem 19 | Francesco Bonazzi 20 | Ismael Rodriguez Espigares 21 | John Chodera 22 | Josh Fass 23 | Stephan Doerr 24 | @vargaslo 25 | Simon Olsson 26 | Brooke Husic 27 | Tim Hempel 28 | Sander Roet 29 | Sebastian Falkner 30 | Finn Krein 31 | Wei-Tse Hsu 32 | Côme Cattin 33 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include LICENSE.txt 3 | include pyproject.toml 4 | 5 | # include test modules in pyemma directory 6 | recursive-include pyemma tests/* tests/data/* 7 | recursive-include pyemma testfiles/* 8 | 9 | # exclude compiled bytecode 10 | global-exclude *.pyc 11 | # exclude git backup files 12 | global-exclude *.orig 13 | 14 | # versioneer 15 | include versioneer.py 16 | include pyemma/_version.py 17 | 18 | # setup stuff 19 | include setup_util.py 20 | 21 | # sources of extensions (incl. cython) 22 | recursive-include pyemma *.pyx *.h *.c 23 | 24 | # do not include eventually present eggs (installed during setup runtime) 25 | prune .eggs 26 | 27 | recursive-include ext/pybind11/include *.h 28 | 29 | exclude pyemma/thermo/extensions/mbar/mbar.c \ 30 | pyemma/thermo/extensions/dtram/dtram.c \ 31 | pyemma/thermo/extensions/mbar_direct/mbar_direct.c \ 32 | pyemma/thermo/extensions/trammbar_direct/trammbar_direct.c \ 33 | pyemma/thermo/extensions/util/util.c \ 34 | pyemma/thermo/extensions/bar/bar.c \ 35 | pyemma/thermo/extensions/trammbar/trammbar.c \ 36 | pyemma/thermo/extensions/tram/tram.c \ 37 | pyemma/thermo/extensions/wham/wham.c \ 38 | pyemma/thermo/extensions/tram_direct/tram_direct.c \ 39 | pyemma/_ext/orderedset/_orderedset.c \ 40 | pyemma/_ext/variational/solvers/eig_qr/eig_qr.c \ 41 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - devel 3 | 4 | pr: 5 | - devel 6 | 7 | stages: 8 | - stage: Test 9 | jobs: 10 | - template: ./devtools/azure-pipelines-linux.yml 11 | - template: ./devtools/azure-pipelines-osx.yml 12 | - template: ./devtools/azure-pipelines-win.yml 13 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import sys 3 | import os 4 | 5 | # this is import for measuring coverage 6 | assert 'pyemma' not in sys.modules 7 | 8 | 9 | def setup_pyemma_config(): 10 | """ set config flags for testing """ 11 | if 'pyemma' in sys.modules: 12 | pyemma = sys.modules['pyemma'] 13 | pyemma.config.show_progress_bars = False 14 | pyemma.config.coordinates_check_output = True 15 | pyemma.config.use_trajectory_lengths_cache = False 16 | 17 | 18 | def add_np(): 19 | # we enforce legacy string formatting of numpy arrays, because the output format changed in version 1.14, 20 | # leading to failing doctests. 21 | import numpy as np 22 | try: 23 | np.set_printoptions(legacy='1.13') 24 | except TypeError: 25 | pass 26 | 27 | 28 | @pytest.fixture(scope='session') 29 | def session_fixture(): 30 | setup_pyemma_config() 31 | add_np() 32 | 33 | # redirect tempdir to a subdir called pyemma-test-$random to clean all temporary files after testing. 34 | import tempfile, uuid 35 | org = tempfile.gettempdir() 36 | tempfile.tempdir = os.path.join(org, 'pyemma_test-{}'.format(uuid.uuid4())) 37 | print('session temporary dir:', tempfile.tempdir) 38 | try: 39 | os.mkdir(tempfile.tempdir) 40 | except OSError as ose: 41 | if 'exists' not in ose.strerror.lower(): 42 | raise 43 | yield 44 | import shutil 45 | shutil.rmtree(tempfile.tempdir, ignore_errors=True) 46 | -------------------------------------------------------------------------------- /devtools/azure-pipelines-linux.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: 'Linux' 3 | pool: 4 | vmImage: 'ubuntu-22.04' 5 | timeoutInMinutes: 360 6 | 7 | strategy: 8 | matrix: 9 | Python38: 10 | CONDA_PY: '3.8' 11 | CONDA_NPY: '1.18' 12 | Python39: 13 | CONDA_PY: '3.9' 14 | CONDA_NPY: '1.19' 15 | Python310: 16 | CONDA_PY: '3.10' 17 | CONDA_NPY: '1.21' 18 | 19 | maxParallel: 10 20 | 21 | steps: 22 | - template: checkout.yml 23 | - bash: echo "##vso[task.prependpath]$CONDA/bin" 24 | displayName: Add conda to PATH 25 | 26 | - bash: sudo install -d -m 0777 /usr/envs 27 | displayName: Fix Conda permissions 28 | 29 | - template: conda-setup+build.yml 30 | - template: test-results.yml 31 | -------------------------------------------------------------------------------- /devtools/azure-pipelines-osx.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: 3 | displayName: "OS X" 4 | pool: 5 | vmImage: 'macOS-11' 6 | strategy: 7 | matrix: 8 | Python38: 9 | CONDA_PY: '3.8' 10 | CONDA_NPY: '1.18' 11 | Python39: 12 | CONDA_PY: '3.9' 13 | CONDA_NPY: '1.19' 14 | Python310: 15 | CONDA_PY: '3.10' 16 | CONDA_NPY: '1.21' 17 | 18 | steps: 19 | - template: checkout.yml 20 | - bash: echo "##vso[task.prependpath]$CONDA/bin" 21 | displayName: Add conda to PATH 22 | 23 | - script: sudo chmod -R 777 /usr/local/miniconda 24 | displayName: Fix Conda permissions 25 | - script: env 26 | 27 | - template: conda-setup+build.yml 28 | - template: test-results.yml 29 | -------------------------------------------------------------------------------- /devtools/azure-pipelines-win.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: 3 | displayName: Win 4 | pool: 5 | vmImage: "windows-2019" 6 | strategy: 7 | matrix: 8 | Python38: 9 | CONDA_PY: '3.8' 10 | CONDA_NPY: '1.18' 11 | Python39: 12 | CONDA_PY: '3.9' 13 | CONDA_NPY: '1.19' 14 | Python310: 15 | CONDA_PY: '3.10' 16 | CONDA_NPY: '1.21' 17 | 18 | steps: 19 | - template: checkout.yml 20 | - task: BatchScript@1 21 | inputs: 22 | filename: "$(CONDA)\\Scripts\\activate.bat" 23 | modifyEnvironment: True 24 | displayName: Add conda to PATH 25 | - template: conda-setup+build.yml 26 | - template: test-results.yml 27 | -------------------------------------------------------------------------------- /devtools/checkout.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - checkout: self 3 | submodules: true 4 | 5 | -------------------------------------------------------------------------------- /devtools/ci/travis/install_miniconda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # taken from https://raw.githubusercontent.com/broadinstitute/viral-ngs/master/travis/install-conda.sh 3 | set -e 4 | 5 | # the miniconda directory may exist if it has been restored from cache 6 | if [ -d "$MINICONDA_DIR" ] && [ -e "$MINICONDA_DIR/bin/conda" ]; then 7 | echo "Miniconda install already present from cache: $MINICONDA_DIR" 8 | export PATH="$MINICONDA_DIR/bin:$PATH" 9 | hash -r 10 | else # if it does not exist, we need to install miniconda 11 | rm -rf "$MINICONDA_DIR" # remove the directory in case we have an empty cached directory 12 | 13 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 14 | curl -S https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh > miniconda.sh; 15 | else 16 | curl -S https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh > miniconda.sh; 17 | fi 18 | 19 | bash miniconda.sh -b -p "$MINICONDA_DIR" 20 | chown -R "$USER" "$MINICONDA_DIR" 21 | export PATH="$MINICONDA_DIR/bin:$PATH" 22 | hash -r 23 | conda config --set always_yes yes \ 24 | --set changeps1 no \ 25 | --set quiet yes \ 26 | --set auto_update_conda false \ 27 | --system # important to write to system cfg, otherwise we loose the changes upon cache reloading. 28 | #conda config --system --add channels conda-forge 29 | #conda install conda 30 | fi 31 | 32 | # we want to have an up to date conda-build. 33 | conda install conda-build=3 34 | conda info -a # for debugging 35 | -------------------------------------------------------------------------------- /devtools/ci/travis/make_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function install_deps { 3 | wget https://github.com/jgm/pandoc/releases/download/1.13.2/pandoc-1.13.2-1-amd64.deb \ 4 | -O pandoc.deb 5 | dpkg -x pandoc.deb $HOME 6 | 7 | export PATH=$PATH:$HOME/usr/bin 8 | # try to execute pandoc 9 | pandoc --version 10 | 11 | conda install -q --yes $doc_deps 12 | pip install -r requirements-build-doc.txt wheel 13 | } 14 | 15 | function build_doc { 16 | pushd doc; make ipython-rst html 17 | # workaround for docs dir => move doc to build/docs afterwards 18 | # travis (currently )expects docs in build/docs (should contain index.html?) 19 | mv build/html ../build/docs 20 | popd 21 | } 22 | 23 | function deploy_doc { 24 | echo "[distutils] 25 | index-servers = pypi 26 | 27 | [pypi] 28 | username:marscher 29 | password:${pypi_pass}" > ~/.pypirc 30 | 31 | python setup.py upload_docs 32 | } 33 | 34 | # build docs only for python 2.7 and for normal commits (not pull requests) 35 | if [[ $TRAVIS_PYTHON_VERSION = "2.7" ]] && [[ "${TRAVIS_PULL_REQUEST}" = "false" ]]; then 36 | install_deps 37 | build_doc 38 | deploy_doc 39 | fi 40 | -------------------------------------------------------------------------------- /devtools/conda-recipe/matplotlibrc: -------------------------------------------------------------------------------- 1 | backend: agg -------------------------------------------------------------------------------- /devtools/conda-recipe/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: pyemma-dev 3 | # version number: [base tag]+[commits-upstream]_[git_hash] 4 | # eg. 2.0+0_g8824162 5 | version: {{ GIT_DESCRIBE_TAG[1:] + '+' + GIT_DESCRIBE_NUMBER + '.' + GIT_DESCRIBE_HASH}} 6 | 7 | source: 8 | path: ../.. 9 | # borked, but preferable, because it creates a "clean" working copy locally. 10 | #git_url: ../../ 11 | 12 | build: 13 | script_env: 14 | - OMP_NUM_THREADS 15 | - PYEMMA_NJOBS 16 | script: "{{ PYTHON }} -m pip install . --no-deps --ignore-installed --no-cache-dir -vvv" 17 | # workaround for bpo-24935, the compiler jinja2 template sets CC, but LDSHARED is not being set accordingly by distutils.sysconfig. 18 | script: LDSHARED="$CC -shared" python setup.py install --single-version-externally-managed --record record.txt # [linux and py35] 19 | 20 | requirements: 21 | build: 22 | - {{ compiler('c') }} 23 | - {{ compiler('cxx') }} 24 | - llvm-openmp # [osx] 25 | - intel-openmp # [osx] 26 | 27 | host: 28 | - cython 29 | - intel-openmp # [osx] 30 | - mdtraj 31 | - numpy 32 | - python 33 | - scipy 34 | - setuptools 35 | - pip 36 | - pybind11 37 | - pybind11-abi 38 | - deeptime >=0.3.0 39 | 40 | run: 41 | - decorator >=4.0.0 42 | - h5py 43 | - intel-openmp # [osx] 44 | - matplotlib 45 | - mdtraj >=1.8 46 | - {{ pin_compatible('numpy') }} 47 | - pathos 48 | - psutil >3.1 49 | - python 50 | - pyyaml 51 | - scipy 52 | - setuptools 53 | - tqdm 54 | - deeptime 55 | 56 | test: 57 | source_files: 58 | - conftest.py 59 | - setup.cfg 60 | files: 61 | - matplotlibrc 62 | requires: 63 | - scikit-learn 64 | - pytest 65 | - pytest-cov 66 | - pytest-faulthandler 67 | - pytest-sugar 68 | - pytest-xdist 69 | 70 | about: 71 | home: http://emma-project.org 72 | license: GNU Lesser Public License v3+ 73 | summary: "EMMA: Emma's Markov Model Algorithms" 74 | -------------------------------------------------------------------------------- /devtools/conda-recipe/run_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import tempfile 4 | 5 | import pytest 6 | 7 | test_pkg = 'pyemma' 8 | cover_pkg = test_pkg 9 | 10 | # where to write junit xml 11 | xml_results_dest = os.getenv('SYSTEM_DEFAULTWORKINGDIRECTORY', tempfile.gettempdir()) 12 | assert os.path.isdir(xml_results_dest), 'no dest dir available' 13 | target_dir = os.path.dirname(xml_results_dest) 14 | if not os.path.exists(target_dir): 15 | os.makedirs(target_dir) 16 | 17 | junit_xml = os.path.join(xml_results_dest, 'junit.xml') 18 | cov_xml = os.path.join(xml_results_dest, 'coverage.xml') 19 | 20 | print('junit destination:', junit_xml) 21 | njobs_args = '-p no:xdist' # if os.getenv('TRAVIS') else '-n2' 22 | 23 | pytest_args = ("-v --pyargs {test_pkg} " 24 | "--cov={cover_pkg} " 25 | "--cov-report=xml:{dest_report} " 26 | "--doctest-modules " 27 | "{njobs_args} " 28 | "--junit-xml={junit_xml} " 29 | "-c {pytest_cfg} " 30 | "--durations=20 " 31 | .format(test_pkg=test_pkg, cover_pkg=cover_pkg, 32 | junit_xml=junit_xml, pytest_cfg='setup.cfg', 33 | dest_report=cov_xml, njobs_args=njobs_args) 34 | .split(' ')) 35 | 36 | print("args:", pytest_args) 37 | print('cwd:', os.getcwd()) 38 | print('content:\n', os.listdir(os.getcwd())) 39 | 40 | if __name__ == '__main__': 41 | res = pytest.main(pytest_args) 42 | sys.exit(res) 43 | 44 | -------------------------------------------------------------------------------- /devtools/conda-setup+build.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - bash: | 3 | conda config --add channels conda-forge 4 | conda config --set always_yes true 5 | conda config --set quiet true 6 | displayName: Configure conda 7 | - bash: | 8 | conda clean --all 9 | conda install mamba 10 | mamba update --all 11 | displayName: Update conda 12 | - bash: | 13 | mamba install boa conda-build conda-verify pip 14 | displayName: 'Install dependencies' 15 | continueOnError: false 16 | - bash: | 17 | export PYTHONUNBUFFERED=1 18 | conda mambabuild devtools/conda-recipe 19 | displayName: 'Build and test' 20 | continueOnError: false 21 | -------------------------------------------------------------------------------- /devtools/doc-recipe/README.txt: -------------------------------------------------------------------------------- 1 | This recipe uses the build from ../conda-recipe which produces a conda-package named pyemma-dev 2 | and builds the sphinx docs matching this package. 3 | -------------------------------------------------------------------------------- /devtools/doc-recipe/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash -x 2 | 3 | set -x 4 | 5 | # we want to install some dependencies via pip 6 | export PIP_IGNORE_INSTALLED=false 7 | export PIP_NO_INDEX=false 8 | 9 | pyemma_version=`python -c "import pyemma as e; print(e.version)"` 10 | export BUILD_DIR=${PREFIX}/v${pyemma_version} 11 | 12 | # disable progress bars 13 | export PYEMMA_CFG_DIR=`mktemp -d` 14 | python -c "import pyemma; pyemma.config.show_progress_bars=False; pyemma.config.save()"; 15 | # print new config 16 | python -c "import pyemma; print(pyemma.config)" 17 | 18 | # if we have the fu-berlin file system, we copy the unpublished data (bpti) 19 | if [[ -d /group/ag_cmb/pyemma_performance/unpublished ]]; then 20 | cp /group/ag_cmb/pyemma_performance/unpublished ./pyemma-ipython -vuR 21 | fi 22 | 23 | # install requirements, which are not available in conda 24 | pip install -vvv -r requirements-build-doc.txt 25 | 26 | make clean 27 | make html 28 | 29 | # we only want to have the html contents 30 | mv $BUILD_DIR/html/* $BUILD_DIR 31 | rm -rf $BUILD_DIR/doctrees 32 | 33 | # remove the deps from $PREFIX so we have only the docs left. 34 | pip uninstall -y -r requirements-build-doc.txt 35 | -------------------------------------------------------------------------------- /devtools/doc-recipe/meta.yaml: -------------------------------------------------------------------------------- 1 | 2 | package: 3 | name: pyemma-doc 4 | # version number: [base tag]+[commits-upstream]_[git_hash] 5 | # eg. v2.0+0_g8824162 6 | version: "0" 7 | 8 | source: 9 | - path: ../../doc/ 10 | # TODO: does not cure that this file can not be included in docs. (relative path issue) 11 | - path: ../../pyemma/pyemma.cfg 12 | folder: pyemma 13 | 14 | requirements: 15 | build: 16 | - pyemma-dev 17 | - make 18 | - mdshare 19 | - nglview 20 | - nbsphinx 21 | - sphinx 22 | - ipython 23 | - ipywidgets 24 | - sphinx_rtd_theme 25 | - pip 26 | - matplotlib 27 | 28 | build: 29 | #noarch: generic 30 | script_env: 31 | # options for sphinx builder 32 | - SPHINXOPTS 33 | # options for notebook conversion (jupyter nbconvert) 34 | - nbflags 35 | # cfg dir 36 | - PYEMMA_CFG_DIR 37 | -------------------------------------------------------------------------------- /devtools/test-results.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | 3 | - task: PublishTestResults@2 4 | inputs: 5 | testResultsFormat: 'JUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest 6 | testResultsFiles: '**/*junit.xml' 7 | failTaskOnFailedTests: true # Optional 8 | publishRunAttachments: true # Optional 9 | 10 | - task: PublishCodeCoverageResults@1 11 | inputs: 12 | codeCoverageTool: 'cobertura' # Options: cobertura, jaCoCo 13 | summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage.xml' 14 | pathToSources: '$(Build.SourcesDirectory)/pyemma' # Optional 15 | #reportDirectory: # Optional 16 | #additionalCodeCoverageFiles: # Optional 17 | #failIfCoverageEmpty: false # Optional 18 | 19 | - bash: curl -s https://codecov.io/bash | bash 20 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | source/generated 2 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | SHELL := /bin/bash 5 | 6 | # You can set these variables from the command line. 7 | SPHINXOPTS = -j8 -v 8 | SPHINXBUILD = LANG=C sphinx-build 9 | PAPER = 10 | 11 | BUILD_DIR?=build 12 | FILES= 13 | 14 | # Internal variables. 15 | PAPEROPT_a4 = -D latex_paper_size=a4 16 | PAPEROPT_letter = -D latex_paper_size=letter 17 | ALLSPHINXOPTS = -d $(BUILD_DIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 18 | 19 | .PHONY: help clean html 20 | 21 | #------------------------------------------------------------------------------ 22 | all: html 23 | help: 24 | @echo "Please use \`make ' where is one of" 25 | @echo " html to make standalone HTML files" 26 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 27 | 28 | clean: 29 | -rm -rf $(BUILD_DIR)/* source/generated source/api/generated 30 | 31 | html: 32 | mkdir -p $(BUILD_DIR)/html $(BUILD_DIR)/doctrees 33 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILD_DIR)/html $(FILES) 34 | @echo 35 | @echo "Build finished. The HTML pages are in build/html." 36 | 37 | out_dir: 38 | mkdir -p source/generated 39 | 40 | latex: 41 | mkdir -p build/latex build/doctrees 42 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex $(FILES) 43 | 44 | html_check: 45 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/html $(FILES) 46 | 47 | -------------------------------------------------------------------------------- /doc/README.rst: -------------------------------------------------------------------------------- 1 | Building the documentation 2 | ========================== 3 | 4 | In order to build the documentation you need to install the requirements 5 | via the following command:: 6 | 7 | pip install -r requirements-build-doc.txt 8 | 9 | 10 | This will mainly drag in sphinx, matplotlib, jupyter notebooks and some small utilities. 11 | 12 | 13 | After you have successfully installed these dependencies, you can invoke:: 14 | 15 | make ipython-rst 16 | 17 | to execute and convert the notebooks found in ../pyemma-ipython 18 | 19 | After this step you are ready to convert the generated RST files to HTML via:: 20 | 21 | make html 22 | 23 | 24 | Note that for a quick build you can safely omit the ipython-rst step. 25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/requirements-build-doc.txt: -------------------------------------------------------------------------------- 1 | sphinx-issues 2 | 3 | # theme 4 | msmb_theme>=1.2 5 | -------------------------------------------------------------------------------- /doc/source/_static/custom.css: -------------------------------------------------------------------------------- 1 | .deprecated { 2 | background-color: #ee4b2b; 3 | } 4 | -------------------------------------------------------------------------------- /doc/source/_static/emma-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/doc/source/_static/emma-logo.png -------------------------------------------------------------------------------- /doc/source/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/doc/source/_static/favicon.ico -------------------------------------------------------------------------------- /doc/source/_static/pyemma_paper_doi.svg: -------------------------------------------------------------------------------- 1 | doidoi10.1021/acs.jctc.5b0074310.1021/acs.jctc.5b00743 -------------------------------------------------------------------------------- /doc/source/api/coordinates.clustering.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pyemma.coordinates.clustering 2 | 3 | .. toctree:: 4 | :maxdepth: 1 -------------------------------------------------------------------------------- /doc/source/api/coordinates.data.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pyemma.coordinates.data 2 | 3 | .. toctree:: 4 | :maxdepth: 1 -------------------------------------------------------------------------------- /doc/source/api/coordinates.pipelines.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pyemma.coordinates.pipelines 2 | 3 | .. toctree:: 4 | :maxdepth: 1 -------------------------------------------------------------------------------- /doc/source/api/coordinates.transform.rst: -------------------------------------------------------------------------------- 1 | .. automodule:: pyemma.coordinates.transform 2 | 3 | .. toctree:: 4 | :maxdepth: 1 -------------------------------------------------------------------------------- /doc/source/api/index.rst: -------------------------------------------------------------------------------- 1 | .. _ref_api: 2 | 3 | ============= 4 | Documentation 5 | ============= 6 | 7 | PyEMMA is a Python library and can be used through python or ipython. 8 | See Tutorials for examples and getting started. 9 | The API (Application Programming Interface) is currently divided into two main packages: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | index_coor 15 | index_msm 16 | index_thermo 17 | 18 | Plotting functions for aiding in the scientific analysis are found here: 19 | 20 | .. toctree:: 21 | :maxdepth: 2 22 | 23 | index_plots 24 | 25 | For saving and loading in PyEMMA take a brief look here: 26 | 27 | .. toctree:: 28 | :maxdepth: 1 29 | 30 | index_serialization 31 | -------------------------------------------------------------------------------- /doc/source/api/index_coor.rst: -------------------------------------------------------------------------------- 1 | .. _ref-coordinates: 2 | 3 | Coordinates package (pyemma.coordinates) 4 | ======================================== 5 | The *coordinates* package contains tools to select features from MD-trajectories. 6 | It also assigns them to a discrete state space, which will be later used in Markov 7 | modeling. 8 | 9 | It supports reading from MD-trajectories, comma separated value ASCII files and 10 | NumPy arrays. The discretized trajectories are being stored as NumPy arrays of 11 | integers. 12 | 13 | .. automodule:: pyemma.coordinates 14 | 15 | .. toctree:: 16 | :maxdepth: 1 17 | 18 | 19 | .. include impl detail here hidden, to get generate docs for these 20 | as sometimes api doc links to them. 21 | 22 | Implementation 23 | -------------- 24 | .. toctree:: 25 | :maxdepth: 1 26 | 27 | coordinates.clustering 28 | coordinates.data 29 | coordinates.transform 30 | coordinates.pipelines 31 | -------------------------------------------------------------------------------- /doc/source/api/index_msm.rst: -------------------------------------------------------------------------------- 1 | .. _msm_api: 2 | 3 | Markov State Models package (pyemma.msm) 4 | ======================================== 5 | The *msm* package provides functions to estimate, analyze and generate 6 | discrete-state Markov models. 7 | All public functions accept dense NumPy and sparse SciPy 8 | matrices and automatically choose the corresponding implementation. 9 | 10 | .. automodule:: pyemma.msm 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | -------------------------------------------------------------------------------- /doc/source/api/index_plots.rst: -------------------------------------------------------------------------------- 1 | .. _ref-plotting: 2 | 3 | Plotting package 4 | ================ 5 | The *plots* package provides tools to plot scientific data generated by pyEMMA 6 | 7 | .. automodule:: pyemma.plots 8 | 9 | .. toctree:: 10 | :maxdepth: 1 11 | -------------------------------------------------------------------------------- /doc/source/api/index_serialization.rst: -------------------------------------------------------------------------------- 1 | 2 | Model serialization 3 | =================== 4 | 5 | In PyEMMA most Estimators and Models can be saved to disk in an efficient file format. 6 | Most of the Estimators and Models in PyEMMA are serializable. If a given PyEMMA object can be saved to disk, 7 | it provides a save method: 8 | 9 | .. automethod:: 10 | pyemma._base.serialization.SerializableMixIn.save 11 | 12 | 13 | Use the load function to load a previously saved PyEMMA object. Since a file can contain multiple 14 | objects saved under different names, you can inspect the files with the :func:`pyemma.list_models` function 15 | to obtain the previously used names. There is also a command line utility `pyemma_list_models` to inspect these files 16 | quickly, without the need launching your own Python script. 17 | 18 | .. autofunction:: 19 | pyemma.load 20 | 21 | .. autofunction:: 22 | pyemma.list_models 23 | 24 | 25 | Notes 26 | ----- 27 | 28 | We try our best to provide future compatibility for previously saved data. This means it should always be possible to load 29 | data with a newer version of the software. However, you can not do reverse; e.g., load a model saved by a new version with 30 | an old version of PyEMMA. 31 | 32 | -------------------------------------------------------------------------------- /doc/source/api/index_thermo.rst: -------------------------------------------------------------------------------- 1 | .. _thermo_api: 2 | 3 | Thermo package (pyemma.thermo) 4 | ============================== 5 | The *thermo* package provides functions to analyze data originating from 6 | potentially biased multi-ensemble MD-Simulations. 7 | 8 | .. automodule:: pyemma.thermo 9 | 10 | .. toctree:: 11 | :maxdepth: 1 -------------------------------------------------------------------------------- /doc/source/ipython.rst: -------------------------------------------------------------------------------- 1 | .. _ref-notebooks_legacy: 2 | 3 | 4 | Legacy Jupyter Notebook Tutorials 5 | ================================= 6 | 7 | These Jupyter (http://jupyter.org) notebooks show the usage of 8 | the PyEMMA API in action and also describe the workflow of Markov model 9 | building. 10 | 11 | You can download a copy of all notebooks and most of the used data 12 | `here `_. 13 | Note that the trajectory of the D.E. Shaw BPTI simulation trajectory is not included 14 | in this archive, since we're not permitted to share this data. Thus the corresponding 15 | notebooks can't be run without obtaining the simulation trajectory independently. 16 | 17 | Application walkthroughs 18 | ------------------------ 19 | 20 | .. toctree:: 21 | :maxdepth: 1 22 | 23 | legacy-notebooks/applications/pentapeptide_msm/pentapeptide_msm 24 | legacy-notebooks/applications/bpti_msm/MSM_BPTI 25 | 26 | By means of application examples, these notebooks give an overview of following methods: 27 | 28 | * Featurization and MD trajectory input 29 | * Time-lagged independent component analysis (TICA) 30 | * Clustering 31 | * Markov state model (MSM) estimation and validation 32 | * Computing Metastable states and structures, coarse-grained MSMs 33 | * Hidden Markov Models (HMM) 34 | * Transition Path Theory (TPT) 35 | 36 | 37 | Methods 38 | ------- 39 | 40 | In this section we will give you in-depth tutorials on specific methods or concepts. 41 | 42 | .. toctree:: 43 | :maxdepth: 1 44 | 45 | legacy-notebooks/methods/feature_selection/feature_selection 46 | legacy-notebooks/methods/model_selection_validation/model_selection_validation 47 | legacy-notebooks/methods/tpt/tpt 48 | legacy-notebooks/methods/amm/augmented_markov_model_walkthrough 49 | legacy-notebooks/methods/storage/storage 50 | 51 | 52 | Multi-Ensemble Markov state models 53 | ---------------------------------- 54 | 55 | .. toctree:: 56 | :maxdepth: 1 57 | 58 | legacy-notebooks/methods/multi_ensemble/doublewell/PyEMMA.thermo.estimate_multi_temperatur_-_asymmetric_double_well 59 | legacy-notebooks/methods/multi_ensemble/doublewell/PyEMMA.thermo.estimate_umbrella_sampling_-_asymmetric_double_well 60 | 61 | Estimation with fixed equilibrium distribution 62 | ---------------------------------------------- 63 | 64 | .. toctree:: 65 | :maxdepth: 1 66 | 67 | legacy-notebooks/methods/msm_with_given_equilibrium/doublewell/doublewell 68 | legacy-notebooks/methods/msm_with_given_equilibrium/alanine/alanine 69 | -------------------------------------------------------------------------------- /doc/source/legal.rst: -------------------------------------------------------------------------------- 1 | .. _legal-notes-label: 2 | 3 | ============= 4 | Legal Notices 5 | ============= 6 | 7 | Imprint 8 | ======= 9 | 10 | Imprint according to § 6 TDG and § 10 Mediendienstestaatsvertrag 11 | 12 | Institution: 13 | Freie Universität Berlin 14 | Arnimallee 6, 14195 Berlin 15 | 16 | Represented by: 17 | 18 | Prof. Dr. Frank Noé 19 | 20 | Contact: 21 | +49 30 838 75354 22 | frank.noe@fu-berlin.de 23 | 24 | Disclaimer 25 | 26 | Online contents: 27 | 28 | The Webteam of “PyEMMA” reserves the right not to be responsible for the topicality, correctness, completeness 29 | or quality of the information provided. Liability claims regarding damage caused by the use of any information provided, 30 | including any kind of information which is incomplete or incorrect, will therefore be rejected. 31 | All offers are not-binding and without obligation. Parts of the pages or the complete publication including 32 | all offers and information might be extended, changed or partly or completely deleted by the Webteam without separate announcement. 33 | 34 | Referrals and links: 35 | 36 | The Webteam is not responsible for any contents linked or referred to from his pages – unless the Webteam has 37 | full knowlegde of illegal contents and would be able to prevent the visitors of the Research Group site from 38 | viewing those pages. If any damage occurs by the use of information presented there, only the author of the respective 39 | pages might be liable, not the one who has linked to these pages. Furthermore the Webteam is not liable for any postings 40 | or messages published by users of discussion boards, guestbooks or mailinglists provided on their page. 41 | 42 | Copyright: 43 | 44 | The Webteam intended not to use any copyrighted material for the publication or, if not possible, to indicate the 45 | copyright of the respective object. 46 | The copyright for any material created by the Webteam is reserved. Any duplication or use of such diagrams, 47 | sounds or texts in other electronic or printed publications is not permitted without the Webteam’s agreement. 48 | 49 | Legal validity of this disclaimer: 50 | This disclaimer is to be regarded as part of the internet publication which you were referred from. 51 | If sections or individual formulations of this text are not legal or correct, the content or validity of the other 52 | parts remain uninfluenced by this fact. 53 | The text of this disclaimer is based on the services of www.disclaimer.de 54 | 55 | 56 | Data privacy statement 57 | ====================== 58 | 59 | .. _legal-notes-priv-label: 60 | 61 | Server-Log-Files 62 | ---------------- 63 | 64 | We store the following data when you access this page, as well when you import the 65 | Python package. These information will be submitted automatically. In detail the following 66 | data is stored and analyzed: 67 | 68 | * Browser type/version 69 | * Used operating system 70 | * Referrer URL 71 | * Hostname/ mac address of the accessing computer 72 | * Time of retrieval 73 | 74 | 75 | Disable online release checking 76 | ------------------------------- 77 | If you do not want to PyEMMA to check for a new relase upon import, you can disable this feature 78 | by setting the following configuration flag: 79 | 80 | .. code:: python 81 | 82 | import pyemma 83 | pyemma.config.check_version = False 84 | pyemma.config.save() 85 | 86 | 87 | Software License 88 | ================ 89 | 90 | .. literalinclude:: ../../LICENSE.txt 91 | -------------------------------------------------------------------------------- /doc/source/tutorial.rst: -------------------------------------------------------------------------------- 1 | 2 | Learn PyEMMA 3 | ============ 4 | 5 | We provide two major sources of learning materials to master PyEMMA, our collection of Jupyter notebook tutorials and 6 | videos of talks given at our annual workshop. 7 | 8 | The notebooks are a collection of complete application walk-throughs capturing the most important aspects of building and 9 | analyzing a Markov state model. 10 | 11 | 12 | Jupyter notebook tutorials 13 | -------------------------- 14 | 15 | .. _ref-notebooks: 16 | 17 | By means of three different application examples, these notebooks give an overview of following methods: 18 | 19 | * Featurization and MD trajectory input 20 | * Time-lagged independent component analysis (TICA) 21 | * Clustering 22 | * Markov state model (MSM) estimation and validation 23 | * Computing metastable states and structures, coarse-grained MSMs 24 | * Hidden Markov Models (HMM) 25 | * Transition Path Theory (TPT) 26 | 27 | These tutorials are part of a LiveCOMS journal article and are up to date with the current PyEMMA release. 28 | 29 | You can find the article `here `_. 30 | 31 | If you find a mistake or have suggestions for improving parts of the tutorial, you can file issues and pull requests 32 | for the contents of both the article and the jupyter notebooks `here `_. 33 | 34 | .. toctree:: 35 | :maxdepth: 1 36 | 37 | tutorials/notebooks/00-pentapeptide-showcase 38 | tutorials/notebooks/01-data-io-and-featurization 39 | tutorials/notebooks/02-dimension-reduction-and-discretization 40 | tutorials/notebooks/03-msm-estimation-and-validation 41 | tutorials/notebooks/04-msm-analysis 42 | tutorials/notebooks/05-pcca-tpt 43 | tutorials/notebooks/06-expectations-and-observables 44 | tutorials/notebooks/07-hidden-markov-state-models 45 | tutorials/notebooks/08-common-problems 46 | 47 | 48 | 49 | 50 | Workshop video tutorials 51 | ------------------------ 52 | 53 | On our Youtube channel you will find lectures and talks about: 54 | 55 | * Markov state model theory 56 | * Hidden Markov state models 57 | * Transition path theory 58 | * Enhanced sampling 59 | * Dealing with multi-ensemble molecular dynamics simulations in PyEMMA 60 | * Useful hints about practical issues... 61 | 62 | 63 | 2018 Workshop 64 | ^^^^^^^^^^^^^ 65 | 66 | .. raw:: html 67 | 68 | 69 | 70 | 71 | 2017 Workshop 72 | ^^^^^^^^^^^^^ 73 | 74 | .. raw:: html 75 | 76 | 77 | 78 | | 79 | | 80 | | 81 | 82 | The legacy tutorials (prior version 2.5.5) covering similar aspects and advanced topics can be found here: 83 | 84 | .. toctree:: 85 | :maxdepth: 2 86 | 87 | ipython 88 | -------------------------------------------------------------------------------- /pyemma/_base/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | __author__ = 'noe' 20 | -------------------------------------------------------------------------------- /pyemma/_base/loggable.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | ''' 20 | Created on 30.08.2015 21 | 22 | @author: marscher 23 | ''' 24 | import logging 25 | import weakref 26 | from itertools import count 27 | 28 | __all__ = ['Loggable'] 29 | 30 | 31 | class Loggable(object): 32 | # counting instances of Loggable, incremented by name property. 33 | __ids = count(0) 34 | # holds weak references to instances of this, to clean up logger instances. 35 | __refs = {} 36 | 37 | _loglevel_DEBUG = logging.DEBUG 38 | _loglevel_INFO = logging.INFO 39 | _loglevel_WARN = logging.WARN 40 | _loglevel_ERROR = logging.ERROR 41 | _loglevel_CRITICAL = logging.CRITICAL 42 | 43 | @property 44 | def name(self): 45 | """The name of this instance""" 46 | try: 47 | return self._name 48 | except AttributeError: 49 | self._name = "%s.%s[%i]" % (self.__module__, 50 | self.__class__.__name__, 51 | next(Loggable.__ids)) 52 | return self._name 53 | 54 | @property 55 | def logger(self): 56 | """The logger for this class instance """ 57 | try: 58 | return self._logger_instance 59 | except AttributeError: 60 | self.__create_logger() 61 | return self._logger_instance 62 | 63 | def _logger_is_active(self, level): 64 | """ @param level: int log level (debug=10, info=20, warn=30, error=40, critical=50)""" 65 | return self.logger.level >= level 66 | 67 | def __create_logger(self): 68 | _weak_logger_refs = Loggable.__refs 69 | # creates a logger based on the the attribe "name" of self 70 | self._logger_instance = logging.getLogger(self.name) 71 | 72 | # store a weakref to this instance to clean the logger instance. 73 | logger_id = id(self._logger_instance) 74 | r = weakref.ref(self, Loggable._cleanup_logger(logger_id, self.name)) 75 | _weak_logger_refs[logger_id] = r 76 | 77 | @staticmethod 78 | def _cleanup_logger(logger_id, logger_name): 79 | # callback function used in conjunction with weakref.ref 80 | # removes logger from root manager 81 | 82 | def remove_logger(weak): 83 | d = logging.getLogger().manager.loggerDict 84 | del d[logger_name] 85 | del Loggable.__refs[logger_id] 86 | return remove_logger 87 | -------------------------------------------------------------------------------- /pyemma/_base/parallel.py: -------------------------------------------------------------------------------- 1 | 2 | def get_n_jobs(logger=None): 3 | 4 | def _from_hardware(): 5 | import psutil 6 | count = psutil.cpu_count(logical=True) 7 | if count is None: # this might happen if psutil cannot determine cpu count 8 | count = 1 9 | return count 10 | 11 | def _from_env(var): 12 | import os 13 | e = os.getenv(var, None) 14 | if e: 15 | try: 16 | return int(e) 17 | except ValueError as ve: 18 | if logger is not None: 19 | logger.warning("could not parse env variable '{var}'." 20 | " Value='{val}'. Error={err}." 21 | .format(err=ve, val=e, var=var)) 22 | return None 23 | 24 | slurm_njobs = _from_env('SLURM_CPUS_ON_NODE') # Number of CPUS on the allocated SLURM node. 25 | pyemma_njobs = _from_env('PYEMMA_NJOBS') 26 | 27 | if slurm_njobs and pyemma_njobs: 28 | import warnings 29 | warnings.warn('two settings for n_jobs from environment: PYEMMA_NJOBS and SLURM_CPUS_ON_NODE. ' 30 | 'Respecting the SLURM setting to avoid overprovisioning resources.') 31 | 32 | # slurm njobs will be used preferably. 33 | val = slurm_njobs or pyemma_njobs 34 | if not val: 35 | val = _from_hardware() 36 | if logger is not None: 37 | logger.debug('determined n_jobs: %s', val) 38 | return val 39 | 40 | 41 | class NJobsMixIn(object): 42 | # mixin for sklearn-like estimators (estimation/ctor parameter has to contain n_jobs). 43 | 44 | @property 45 | def n_jobs(self): 46 | """ Returns number of jobs/threads to use during assignment of data. 47 | 48 | Returns 49 | ------- 50 | If None it will return the setting of 'PYEMMA_NJOBS' or 51 | 'SLURM_CPUS_ON_NODE' environment variable. If none of these environment variables exist, 52 | the number of processors /or cores is returned. 53 | 54 | Notes 55 | ----- 56 | This setting will effectively be multiplied by the the number of threads used by NumPy for 57 | algorithms which use multiple processes. So take care if you choose this manually. 58 | """ 59 | if not hasattr(self, '_n_jobs'): 60 | self._n_jobs = get_n_jobs(logger=getattr(self, 'logger')) 61 | return self._n_jobs 62 | 63 | @n_jobs.setter 64 | def n_jobs(self, val): 65 | if val is not None and val == 0: 66 | raise ValueError("n_jobs must not be 0.") 67 | elif val is not None and val < 0: 68 | import warnings 69 | warnings.warn("Negative n_jobs will likely raise in future versions, use None instead.", DeprecationWarning) 70 | val = None 71 | if val is None: 72 | val = get_n_jobs(logger=getattr(self, 'logger')) 73 | self._n_jobs = int(val) 74 | -------------------------------------------------------------------------------- /pyemma/_base/progress/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2017 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | from .reporter import ProgressReporterMixin 20 | from .reporter import ProgressReporter 21 | -------------------------------------------------------------------------------- /pyemma/_base/serialization/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interfacing functions and classing to Serialization. 3 | 4 | Derive from SerializableMixIn to make your class serializable. If you need to patch an old version of your class, 5 | you need the Modifications class. 6 | 7 | """ 8 | 9 | from .serialization import SerializableMixIn, Modifications 10 | 11 | __all__ = ['SerializableMixIn', 'Modifications', 'load', 'list_models'] 12 | 13 | 14 | def load(filename, model_name='default'): 15 | from .serialization import SerializableMixIn 16 | return SerializableMixIn.load(file_name=filename, model_name=model_name) 17 | 18 | 19 | load.__doc__ = SerializableMixIn.load.__doc__ 20 | 21 | 22 | def list_models(filename): 23 | """ Lists all models in given filename. 24 | 25 | Parameters 26 | ---------- 27 | filename: str 28 | path to filename, where the model has been stored. 29 | 30 | Returns 31 | ------- 32 | obj: dict 33 | A mapping by name and a comprehensive description like this: 34 | {model_name: {'repr' : 'string representation, 'created': 'human readable date', ...} 35 | """ 36 | from .h5file import H5File 37 | with H5File(filename, mode='r') as f: 38 | return f.models_descriptive 39 | -------------------------------------------------------------------------------- /pyemma/_base/serialization/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/_base/serialization/tests/__init__.py -------------------------------------------------------------------------------- /pyemma/_base/serialization/tests/_test_classes.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2014-2017 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | import numpy as np 19 | 20 | from pyemma._base.serialization.serialization import SerializableMixIn, Modifications 21 | 22 | 23 | class test_cls_v1(SerializableMixIn): 24 | __serialize_fields = ('a', 'x', 'y') 25 | __serialize_version = 1 26 | 27 | def __init__(self): 28 | self.a = np.array([1, 2, 3]) 29 | self.x = 'foo' 30 | self.y = 0.0 31 | 32 | def __eq__(self, other): 33 | return np.allclose(self.a, other.a) and self.x == other.x and self.y == other.y 34 | 35 | 36 | # note: in the real world this decorator would be invoked here! 37 | #@handle_old_classes('pyemma._base.serialization.tests.test_serialization.test_cls_v1') 38 | class test_cls_v2(SerializableMixIn): 39 | __serialize_fields = ('b', 'y', 'z') 40 | __serialize_version = 2 41 | # interpolate from version 1: add attr z with value 42 42 | __serialize_modifications_map = {1: Modifications().set('z', 42).mv('a', 'b').rm('x').list()} 43 | 44 | def __init__(self): 45 | self.b = np.array([1, 2, 3]) 46 | self.y = 0.0 47 | self.z = 42 48 | 49 | def __eq__(self, other): 50 | return np.allclose(self.b, other.b) and self.y == other.y and self.z == other.z 51 | 52 | 53 | class test_cls_v3(SerializableMixIn): 54 | # should fake the refactoring of new_cls 55 | __serialize_fields = ('c', 'z') 56 | __serialize_version = 3 57 | # interpolate from version 1 and 2 58 | __serialize_modifications_map = {1: Modifications().set('z', 42).mv('a', 'b').rm('x').list(), 59 | 2: Modifications().set('z', 23).mv('b', 'c').rm('y').list()} 60 | 61 | def __init__(self): 62 | self.c = np.array([1, 2, 3]) 63 | self.z = 23 64 | 65 | def __eq__(self, other): 66 | return np.allclose(self.c, other.c) and self.y == other.y and self.z == other.z 67 | 68 | 69 | class _deleted_in_old_version(test_cls_v3): 70 | __serialize_version = 4 71 | 72 | def __init__(self): 73 | super(_deleted_in_old_version, self).__init__() 74 | 75 | 76 | class test_cls_with_old_locations(_deleted_in_old_version): 77 | __serialize_version = 5 78 | 79 | def __init__(self): 80 | super(test_cls_with_old_locations, self).__init__() 81 | 82 | 83 | class to_interpolate_with_functions(test_cls_v1): 84 | 85 | @staticmethod 86 | def map_y(x): 87 | return 42 88 | 89 | __serialize_version = 2 90 | # map from version 1 to 2 91 | __serialize_modifications_map = {1: Modifications().map('y', map_y).list()} 92 | -------------------------------------------------------------------------------- /pyemma/_base/serialization/tests/test_cli.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2014-2017 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | import shutil 19 | import tempfile 20 | 21 | import pytest 22 | from numpy.testing import assert_ 23 | 24 | from pyemma._base.serialization.cli import main 25 | from pyemma.coordinates import source, tica, cluster_kmeans 26 | 27 | 28 | @pytest.fixture 29 | def model_file(): 30 | file = None 31 | try: 32 | from pyemma.datasets import get_bpti_test_data 33 | d = get_bpti_test_data() 34 | trajs, top = d['trajs'], d['top'] 35 | s = source(trajs, top=top) 36 | 37 | t = tica(s, lag=1) 38 | 39 | c = cluster_kmeans(t) 40 | file = tempfile.mktemp() 41 | c.save(file, save_streaming_chain=True) 42 | 43 | yield file 44 | finally: 45 | if file is not None: 46 | shutil.rmtree(file, ignore_errors=True) 47 | 48 | 49 | def test_recursive(model_file): 50 | """ check the whole chain has been printed""" 51 | from pyemma.util.contexts import Capturing 52 | with Capturing() as out: 53 | main(['--recursive', model_file]) 54 | assert out 55 | all_out = '\n'.join(out) 56 | assert_('FeatureReader' in all_out) 57 | assert_('TICA' in all_out) 58 | assert_('Kmeans' in all_out) 59 | -------------------------------------------------------------------------------- /pyemma/_base/serialization/tests/test_topology.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2014-2017 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | import os 19 | import tempfile 20 | import unittest 21 | import pkg_resources 22 | import mdtraj 23 | 24 | from pyemma._base.serialization.h5file import H5File 25 | 26 | 27 | class TestTopology(unittest.TestCase): 28 | maxDiff = None 29 | 30 | def setUp(self): 31 | self.f = tempfile.mktemp('.h5') 32 | 33 | def tearDown(self): 34 | os.unlink(self.f) 35 | 36 | def _load_cmp(self, pdb): 37 | top = mdtraj.load(pdb).top 38 | with H5File(self.f, mode='a') as fh: 39 | fh.add_object('top', top) 40 | restored = fh.model 41 | 42 | assert top == restored 43 | assert tuple(top.atoms) == tuple(restored.atoms) 44 | assert tuple(top.bonds) == tuple(restored.bonds) 45 | 46 | # mdtraj (1.9.1) does not impl eq for Residue... 47 | def eq(self, other): 48 | from mdtraj.core.topology import Residue 49 | if not isinstance(other, Residue): 50 | return False 51 | return (self.index == other.index 52 | and self.resSeq == other.resSeq 53 | and other.name == self.name 54 | and tuple(other.atoms) == tuple(self.atoms)) 55 | 56 | from unittest import mock 57 | with mock.patch('mdtraj.core.topology.Residue.__eq__', eq): 58 | self.assertEqual(tuple(top.residues), tuple(restored.residues)) 59 | 60 | def test_opsin(self): 61 | traj = pkg_resources.resource_filename('pyemma.coordinates.tests', 'data/opsin_aa_1_frame.pdb.gz') 62 | self._load_cmp(traj) 63 | 64 | def test_bpti(self): 65 | traj = pkg_resources.resource_filename('pyemma.coordinates.tests', 'data/bpti_ca.pdb') 66 | self._load_cmp(traj) 67 | -------------------------------------------------------------------------------- /pyemma/_base/serialization/util.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2014-2017 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | from collections import defaultdict 19 | 20 | __author_ = 'marscher' 21 | 22 | 23 | class _ClassRenameRegistry(object): 24 | """ perform a mapping between old and new names and reverse. 25 | A class can be renamed multiple times. """ 26 | 27 | def __init__(self): 28 | self._old_to_new = {} 29 | self._new_to_old = defaultdict(list) 30 | 31 | def add_mapping(self, location, new_cls): 32 | if isinstance(location, str): 33 | location = [location] 34 | assert hasattr(new_cls, "__module__"), "makes only sense for importable classes." 35 | for old in location: 36 | self._old_to_new[old] = new_cls 37 | self._new_to_old[new_cls].append(old) 38 | 39 | def clear(self): 40 | self._old_to_new.clear() 41 | self._new_to_old.clear() 42 | 43 | def find_replacement_for_old(self, old): 44 | return self._old_to_new.get(old, None) 45 | 46 | def old_handled_by(self, klass): 47 | return self._new_to_old.get(klass, ()) 48 | 49 | 50 | class_rename_registry = _ClassRenameRegistry() 51 | 52 | 53 | class handle_old_classes(object): 54 | """ Updates the renamed classes dictionary for serialization handling. 55 | 56 | The idea is to provide a location/name history to the current decorated class, 57 | so old occurrences can be easily mapped to the current name upon loading old models. 58 | 59 | Parameters 60 | ---------- 61 | locations: list, tuple of string 62 | the elements are dotted python names to classes. 63 | """ 64 | 65 | def __init__(self, locations): 66 | if not isinstance(locations, (tuple, list)): 67 | locations = [locations] 68 | assert all(isinstance(x, str) for x in locations) 69 | self.locations = locations 70 | 71 | def __call__(self, cls): 72 | class_rename_registry.add_mapping(self.locations, cls) 73 | return cls 74 | 75 | 76 | def _importable_name(cls): 77 | name = cls.__name__ 78 | module = cls.__module__ 79 | return '%s.%s' % (module, name) 80 | -------------------------------------------------------------------------------- /pyemma/_base/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/_base/tests/__init__.py -------------------------------------------------------------------------------- /pyemma/_base/tests/test_estimator.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from pyemma._base.estimator import Estimator 4 | 5 | try: 6 | import sklearn 7 | 8 | have_sklearn = True 9 | except ImportError: 10 | have_sklearn = False 11 | 12 | 13 | class TestBaseEstimator(unittest.TestCase): 14 | 15 | @unittest.skipIf(not have_sklearn, 'no sklearn') 16 | def test_sklearn_compat_fit(self): 17 | class T(Estimator): 18 | def _estimate(self, X): 19 | return self 20 | 21 | from sklearn.pipeline import Pipeline 22 | p = Pipeline([('test', T())]) 23 | p.fit([1, 2, 3]) 24 | -------------------------------------------------------------------------------- /pyemma/_ext/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | __author__ = 'noe' 20 | -------------------------------------------------------------------------------- /pyemma/_ext/orderedset/.gitignore: -------------------------------------------------------------------------------- 1 | _orderedset.c 2 | -------------------------------------------------------------------------------- /pyemma/_ext/orderedset/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | __version__ = '2.0' 3 | 4 | 5 | from ._orderedset import OrderedSet -------------------------------------------------------------------------------- /pyemma/_ext/sklearn/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/_ext/sklearn/__init__.py -------------------------------------------------------------------------------- /pyemma/_ext/variational/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'noe' 2 | 3 | # import subpackages such that they are available after the main package import 4 | from . import estimators 5 | from . import solvers 6 | 7 | # direct imports of important functions/classes to-level API 8 | from .solvers.direct import eig_corr, spd_eig, spd_inv, spd_inv_split, spd_inv_sqrt, sort_by_norm 9 | from .solvers.eig_qr.eig_qr import eig_qr 10 | 11 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/estimators/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from .moments import moments_XX, moments_XXXY, moments_block 3 | from .moments import covar, covars 4 | from .running_moments import RunningCovar, running_covar 5 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/estimators/covar_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.12) 2 | project (covartools) 3 | 4 | 5 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../../../pybind11 6 | ${CMAKE_CURRENT_BINARY_DIR}/pybind11) 7 | pybind11_add_module(_covartools covartools.cpp) 8 | 9 | include_directories(.) 10 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/estimators/covar_c/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'noe' 2 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/estimators/covar_c/covartools.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "covartools_cpp.h" 4 | 5 | namespace py = pybind11; 6 | 7 | 8 | PYBIND11_MODULE(_covartools, m) { 9 | m.doc() = "covariance computation utilities."; 10 | 11 | // ================================================ 12 | // Check for constant columns 13 | // ================================================ 14 | m.def("variable_cols_char", &_variable_cols); 15 | m.def("variable_cols_int", &_variable_cols); 16 | m.def("variable_cols_long", &_variable_cols); 17 | m.def("variable_cols_float", &_variable_cols); 18 | m.def("variable_cols_double", &_variable_cols); 19 | } 20 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/estimators/covar_c/covartools.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | 3 | 4 | def variable_cols(X, tol=0.0, min_constant=0): 5 | """ Evaluates which columns are constant (0) or variable (1) 6 | 7 | Parameters 8 | ---------- 9 | X : ndarray 10 | Matrix whose columns will be checked for constant or variable. 11 | tol : float 12 | Tolerance for float-matrices. When set to 0 only equal columns with 13 | values will be considered constant. When set to a positive value, 14 | columns where all elements have absolute differences to the first 15 | element of that column are considered constant. 16 | min_constant : int 17 | Minimal number of constant columns to resume operation. If at one 18 | point the number of constant columns drops below min_constant, the 19 | computation will stop and all columns will be assumed to be variable. 20 | In this case, an all-True array will be returned. 21 | 22 | Returns 23 | ------- 24 | variable : bool-array 25 | Array with number of elements equal to the columns. True: column is 26 | variable / non-constant. False: column is constant. 27 | 28 | """ 29 | if X is None: 30 | return None 31 | from pyemma._ext.variational.estimators.covar_c._covartools import (variable_cols_double, 32 | variable_cols_float, 33 | variable_cols_int, 34 | variable_cols_long, 35 | variable_cols_char) 36 | # prepare column array 37 | cols = numpy.zeros(X.shape[1], dtype=numpy.bool_, order='C') 38 | 39 | if X.dtype == numpy.float64: 40 | completed = variable_cols_double(cols, X, tol, min_constant) 41 | elif X.dtype == numpy.float32: 42 | completed = variable_cols_float(cols, X, tol, min_constant) 43 | elif X.dtype == numpy.int32: 44 | completed = variable_cols_int(cols, X, 0, min_constant) 45 | elif X.dtype == numpy.int64: 46 | completed = variable_cols_long(cols, X, 0, min_constant) 47 | elif X.dtype == numpy.bool_: 48 | completed = variable_cols_char(cols, X, 0, min_constant) 49 | else: 50 | raise TypeError('unsupported type of X: %s' % X.dtype) 51 | 52 | # if interrupted, return all ones. Otherwise return the variable columns as bool array 53 | if completed == 0: 54 | return numpy.ones_like(cols, dtype=numpy.bool_) 55 | 56 | return cols 57 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/estimators/covar_c/covartools_cpp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace py = pybind11; 8 | 9 | 10 | /** Checks each column whether it is constant in the rows or not 11 | 12 | @param cols : (N) result array that will be filled with 0 (column constant) or 1 (column variable) 13 | @param X : (M, N) array 14 | @param M : int 15 | @param N : int 16 | 17 | */ 18 | template 19 | int _variable_cols(py::array_t &np_cols, 20 | const py::array_t &np_X, 21 | float tol=0, std::size_t min_constant=0) { 22 | // compare first and last row to get constant candidates 23 | std::size_t i, j; 24 | std::size_t ro; 25 | std::size_t M = np_X.shape(0), N = np_X.shape(1); 26 | dtype diff; 27 | std::size_t nconstant = N; // current number of constant columns 28 | auto cols = np_cols.mutable_data(0); 29 | auto X = np_X.data(0); 30 | // by default all 0 (constant) 31 | for (j = 0; j < N; j++) 32 | cols[j] = false; 33 | 34 | // go through all rows in order to confirm constant candidates 35 | for (i = 0; i < M; i++) { 36 | ro = i * N; 37 | for (j = 0; j < N; j++) { 38 | if (! cols[j]) { 39 | // note: the compiler will eliminate this branch, if dtype != (float, double) 40 | if (std::is_floating_point::value) { 41 | diff = std::abs(X[j] - X[ro + j]); 42 | if (diff >= tol) { 43 | cols[j] = true; 44 | nconstant--; 45 | // are constant columns below threshold? Then interrupt. 46 | if (nconstant < min_constant) 47 | return 0; 48 | // do we have 0 constant columns? Then we can stop regularly. 49 | if (nconstant == 0) 50 | return 1; 51 | } 52 | } else { 53 | if (X[j] != X[ro + j]) { 54 | cols[j] = true; 55 | nconstant--; 56 | if (nconstant < min_constant) 57 | return 0; 58 | if (nconstant == 0) 59 | return 1; 60 | } 61 | } 62 | } 63 | } 64 | } 65 | return 1; 66 | } 67 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/estimators/tests/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'noe' 2 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/solvers/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'noe' 2 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/solvers/eig_qr/.gitignore: -------------------------------------------------------------------------------- 1 | eig_qr.c 2 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/solvers/eig_qr/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'noe' -------------------------------------------------------------------------------- /pyemma/_ext/variational/solvers/eig_qr/eig_qr.pyx: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | cimport scipy.linalg.cython_lapack as scc 3 | 4 | def eig_qr(A): 5 | """ Compute eigenvalues and eigenvectors of symmetric matrix A using symmetric tridiagonal QR-algorithm 6 | with implicit shifts. The matrix is first transformed to tridiagonal shape using lapack's dsytrd routine. 7 | Then, the tridiagonal QR-iteration is performed using lapack's dsteqr routine. 8 | 9 | Parameters: 10 | ----------- 11 | A, ndarray (N, N): 12 | symmetric matrix. 13 | 14 | Returns: 15 | -------- 16 | D, ndarray(N,) 17 | array of eigenvalues of A 18 | B, ndarray(N, N) 19 | array of eigenvectors of A. 20 | """ 21 | 22 | # handle 1x1 case 23 | if np.size(A) == 1: # size can handle 1x1 arrays and numbers 24 | return A*np.ones(1), np.ones((1, 1)) 25 | 26 | # Definitions: 27 | array_args = dict(dtype=np.float64, order='F') 28 | cdef double[:,:] B = np.require(A, dtype=np.float64, requirements=('F', 'A')) 29 | cdef int n = A.shape[0], lda = A.shape[0], info, lwork = -1 30 | cdef char uplo = b"U" 31 | cdef double[:] D = np.zeros(n, **array_args) 32 | cdef double[:] E = np.zeros(n-1, **array_args) 33 | cdef double[:] Tau = np.zeros(n-1, **array_args) 34 | cdef double WorkFake # LAPACK writes back the optimal block size here, when lwork is -1. 35 | 36 | # Transform to tridiagonal shape: 37 | scc.dsytrd(&uplo, &n, &B[0, 0], &lda, &D[0], &E[0], &Tau[0], &WorkFake, &lwork, &info) 38 | assert info == 0, info 39 | lwork = WorkFake 40 | cdef double[:] Work2 = np.zeros(lwork, **array_args) 41 | scc.dsytrd(&uplo, &n, &B[0, 0], &lda, &D[0], &E[0], &Tau[0], &Work2[0], &lwork, &info) 42 | assert info == 0, info 43 | del Work2 44 | 45 | # Extract transformation to tridiagonal shape: 46 | lwork = -1 47 | scc.dorgtr(&uplo, &n, &B[0, 0], &lda, &Tau[0], &WorkFake, &lwork, &info) 48 | assert info == 0, info 49 | lwork = WorkFake 50 | cdef double[:] Work3 = np.zeros(lwork, **array_args) 51 | scc.dorgtr(&uplo, &n, &B[0, 0], &lda, &Tau[0], &Work3[0], &lwork, &info) 52 | assert info == 0, info 53 | del Tau, Work3 54 | 55 | # Run QR-iteration. 56 | cdef double[:] Work4 = np.zeros(max(1, 2*n - 2), **array_args) 57 | cdef char compz = b"V" 58 | scc.dsteqr(&compz, &n, &D[0], &E[0], &B[0, 0], &n, &Work4[0], &info) 59 | assert info == 0, info 60 | 61 | return np.asarray(D), np.asarray(B) 62 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/solvers/tests/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'noe' 2 | -------------------------------------------------------------------------------- /pyemma/_ext/variational/util.py: -------------------------------------------------------------------------------- 1 | """ Add convenience functions here if needed 2 | """ 3 | 4 | __author__ = 'noe' 5 | 6 | import numpy as _np 7 | 8 | class ZeroRankError(_np.linalg.LinAlgError): 9 | """Input matrix has rank zero.""" 10 | pass 11 | 12 | def features_to_basis(infiles, basisset, outfiles): 13 | """Reads input files 14 | 15 | basisset : BasisSet object 16 | basis set tob e used 17 | 18 | References 19 | --------- 20 | .. [5] Vitalini, F., Noe, F. and Keller, B. (2015): 21 | A basis set for peptides for the variational approach to conformational kinetics. (In review). 22 | 23 | """ 24 | # cycle through input files 25 | # read infile 26 | # map to basis function values 27 | # write outfile 28 | pass 29 | -------------------------------------------------------------------------------- /pyemma/coordinates/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r""" 21 | .. currentmodule:: pyemma.coordinates 22 | 23 | User API 24 | ======== 25 | 26 | **Trajectory input/output and featurization** 27 | 28 | .. autosummary:: 29 | :toctree: generated/ 30 | 31 | featurizer 32 | load 33 | source 34 | combine_sources 35 | pipeline 36 | discretizer 37 | save_traj 38 | save_trajs 39 | 40 | **Covariance estimation** 41 | 42 | .. autosummary:: 43 | :toctree: generated/ 44 | 45 | covariance_lagged 46 | 47 | **Coordinate and feature transformations** 48 | 49 | .. autosummary:: 50 | :toctree: generated/ 51 | 52 | pca 53 | tica 54 | vamp 55 | 56 | **Clustering Algorithms** 57 | 58 | .. autosummary:: 59 | :toctree: generated/ 60 | 61 | cluster_kmeans 62 | cluster_mini_batch_kmeans 63 | cluster_regspace 64 | cluster_uniform_time 65 | assign_to_centers 66 | 67 | Classes 68 | ======= 69 | **Coordinate classes** encapsulating complex functionality. You don't need to 70 | construct these classes yourself, as this is done by the user API functions above. 71 | Find here a documentation how to extract features from them. 72 | 73 | **I/O and Featurization** 74 | 75 | .. autosummary:: 76 | :toctree: generated/ 77 | 78 | data.MDFeaturizer 79 | data.CustomFeature 80 | 81 | **Transformation estimators** 82 | 83 | .. autosummary:: 84 | :toctree: generated/ 85 | 86 | transform.PCA 87 | transform.TICA 88 | transform.VAMP 89 | 90 | **Covariance estimation** 91 | 92 | .. autosummary:: 93 | :toctree: generated/ 94 | 95 | estimation.covariance.LaggedCovariance 96 | 97 | **Clustering algorithms** 98 | 99 | .. autosummary:: 100 | :toctree: generated/ 101 | 102 | clustering.KmeansClustering 103 | clustering.MiniBatchKmeansClustering 104 | clustering.RegularSpaceClustering 105 | clustering.UniformTimeClustering 106 | 107 | **Transformers** 108 | 109 | .. autosummary:: 110 | :toctree: generated/ 111 | 112 | data._base.transformer.StreamingTransformer 113 | pipelines.Pipeline 114 | 115 | **Discretization** 116 | 117 | .. autosummary:: 118 | :toctree: generated/ 119 | 120 | clustering.AssignCenters 121 | 122 | 123 | """ 124 | from .api import * 125 | -------------------------------------------------------------------------------- /pyemma/coordinates/clustering/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r""" 21 | =============================================================================== 22 | clustering - Algorithms (:mod:`pyemma.coordinates.clustering`) 23 | =============================================================================== 24 | 25 | .. currentmodule: pyemma.coordinates.clustering 26 | 27 | .. autosummary:: 28 | :toctree: generated/ 29 | 30 | AssignCenters 31 | KmeansClustering 32 | RegularSpaceClustering 33 | UniformTimeClustering 34 | """ 35 | 36 | from .assign import AssignCenters 37 | from .kmeans import KmeansClustering 38 | from .kmeans import MiniBatchKmeansClustering 39 | from .regspace import RegularSpaceClustering 40 | from .uniform_time import UniformTimeClustering 41 | -------------------------------------------------------------------------------- /pyemma/coordinates/clustering/src/clustering_module.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by marscher on 7/17/17. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | struct RMSDMetric { 10 | template 11 | static T compute_squared(const T* xs, const T* ys, std::size_t dim) { 12 | if (dim % 3 != 0) { 13 | throw std::range_error("RMSDMetric is only implemented for input data with a dimension divisible by 3."); 14 | } 15 | 16 | float trace_a, trace_b; 17 | auto dim3 = static_cast(dim / 3); 18 | std::vector buffer_a (xs, xs + dim); 19 | std::vector buffer_b (ys, ys + dim); 20 | 21 | inplace_center_and_trace_atom_major(buffer_a.data(), &trace_a, 1, dim3); 22 | inplace_center_and_trace_atom_major(buffer_b.data(), &trace_b, 1, dim3); 23 | 24 | if constexpr(std::is_same::value) { 25 | std::vector cast (xs, xs + dim); 26 | return msd_atom_major(dim3, dim3, cast.data(), buffer_b.data(), trace_a, trace_b, 0, nullptr); 27 | } else { 28 | return msd_atom_major(dim3, dim3, xs, buffer_b.data(), trace_a, trace_b, 0, nullptr); 29 | } 30 | } 31 | 32 | template 33 | static T compute(const T* xs, const T* ys, std::size_t dim) { 34 | return std::sqrt(compute_squared(xs, ys, dim)); 35 | } 36 | }; 37 | 38 | PYBIND11_MODULE(_ext, m) { 39 | auto rmsdModule = m.def_submodule("rmsd"); 40 | deeptime::clustering::registerClusteringImplementation(rmsdModule); 41 | rmsdModule.def("compute_metric", [](py::array_t x, py::array_t y) { 42 | return RMSDMetric::compute(x.data(), y.data(), x.size()); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /pyemma/coordinates/clustering/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/clustering/tests/__init__.py -------------------------------------------------------------------------------- /pyemma/coordinates/clustering/tests/test_cluster_samples.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | """ 21 | Test the save_trajs function of the coordinates API by comparing 22 | the direct, sequential retrieval of frames via mdtraj.load_frame() vs 23 | the retrival via save_trajs 24 | @author: gph82, clonker 25 | """ 26 | 27 | 28 | import unittest 29 | 30 | import numpy as np 31 | import pyemma.coordinates as coor 32 | 33 | class TestClusterSamples(unittest.TestCase): 34 | @classmethod 35 | def setUpClass(cls): 36 | super(TestClusterSamples, cls).setUpClass() 37 | 38 | def setUp(self): 39 | self.input_trajs = [[0,1,2], 40 | [3,4,5], 41 | [6,7,8], 42 | [0,1,2], 43 | [3,4,5], 44 | [6,7,8]] 45 | self.cluster_obj = coor.cluster_regspace(data=self.input_trajs, dmin=.5) 46 | 47 | def test_index_states(self): 48 | # Test that the catalogue is being set up properly 49 | 50 | # The assingment-catalogue is easy to see from the above dtrajs 51 | ref = [[[0,0],[3,0]], # appearances of the 1st cluster 52 | [[0,1],[3,1]], # appearances of the 2nd cluster 53 | [[0,2],[3,2]], # appearances of the 3rd cluster 54 | [[1,0],[4,0]], # ..... 55 | [[1,1],[4,1]], 56 | [[1,2],[4,2]], 57 | [[2,0],[5,0]], 58 | [[2,1],[5,1]], 59 | [[2,2],[5,2]], 60 | ] 61 | 62 | for cc in np.arange(self.cluster_obj.n_clusters): 63 | assert np.allclose(self.cluster_obj.index_clusters[cc], ref[cc]) 64 | 65 | def test_sample_indexes_by_state(self): 66 | samples = self.cluster_obj.sample_indexes_by_cluster(np.arange(self.cluster_obj.n_clusters), 10) 67 | 68 | # For each sample, check that you're actually retrieving the i-th center 69 | for ii, isample in enumerate(samples): 70 | assert np.in1d([self.cluster_obj.dtrajs[pair[0]][pair[1]] for pair in isample],ii).all() 71 | 72 | 73 | if __name__ == "__main__": 74 | unittest.main() 75 | -------------------------------------------------------------------------------- /pyemma/coordinates/clustering/tests/test_uniform_time.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | ''' 21 | Created on 09.04.2015 22 | 23 | @author: marscher 24 | ''' 25 | 26 | import unittest 27 | 28 | import numpy as np 29 | 30 | from pyemma.coordinates import api 31 | from pyemma.coordinates.data.data_in_memory import DataInMemory 32 | 33 | 34 | class TestUniformTimeClustering(unittest.TestCase): 35 | 36 | def test_1d(self): 37 | x = np.random.random(1000) 38 | reader = DataInMemory(x) 39 | 40 | k = 2 41 | c = api.cluster_uniform_time(reader, k=k) 42 | 43 | def test_2d(self): 44 | x = np.random.random((300, 3)) 45 | reader = DataInMemory(x) 46 | 47 | k = 2 48 | c = api.cluster_uniform_time( k=k) 49 | 50 | c.estimate(reader) 51 | 52 | def test_2d_skip(self): 53 | x = np.random.random((300, 3)) 54 | reader = DataInMemory(x) 55 | 56 | k = 2 57 | c = api.cluster_uniform_time(k=k, skip=100) 58 | 59 | c.estimate(reader) 60 | 61 | def test_big_k(self): 62 | x = np.random.random((300, 3)) 63 | reader = DataInMemory(x) 64 | k=151 65 | c = api.cluster_uniform_time(k=k) 66 | 67 | c.estimate(reader) 68 | 69 | 70 | if __name__ == "__main__": 71 | unittest.main() 72 | -------------------------------------------------------------------------------- /pyemma/coordinates/clustering/tests/util.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generate samples of synthetic data sets. 3 | """ 4 | 5 | # Authors: B. Thirion, G. Varoquaux, A. Gramfort, V. Michel, O. Grisel, 6 | # G. Louppe, J. Nothman 7 | # License: BSD 3 clause 8 | 9 | import numbers 10 | import numpy as np 11 | 12 | def make_blobs(n_samples=100, n_features=2, centers=3, cluster_std=1.0, 13 | center_box=(-10.0, 10.0), shuffle=True, random_state=None): 14 | """Generate isotropic Gaussian blobs for clustering. 15 | 16 | Read more in the :ref:`User Guide `. 17 | 18 | Parameters 19 | ---------- 20 | n_samples : int, optional (default=100) 21 | The total number of points equally divided among clusters. 22 | 23 | n_features : int, optional (default=2) 24 | The number of features for each sample. 25 | 26 | centers : int or array of shape [n_centers, n_features], optional 27 | (default=3) 28 | The number of centers to generate, or the fixed center locations. 29 | 30 | cluster_std : float or sequence of floats, optional (default=1.0) 31 | The standard deviation of the clusters. 32 | 33 | center_box : pair of floats (min, max), optional (default=(-10.0, 10.0)) 34 | The bounding box for each cluster center when centers are 35 | generated at random. 36 | 37 | shuffle : boolean, optional (default=True) 38 | Shuffle the samples. 39 | 40 | random_state : int, RandomState instance or None, optional (default=None) 41 | If int, random_state is the seed used by the random number generator; 42 | If RandomState instance, random_state is the random number generator; 43 | If None, the random number generator is the RandomState instance used 44 | by `np.random`. 45 | 46 | Returns 47 | ------- 48 | X : array of shape [n_samples, n_features] 49 | The generated samples. 50 | 51 | y : array of shape [n_samples] 52 | The integer labels for cluster membership of each sample. 53 | 54 | """ 55 | from scipy._lib._util import check_random_state 56 | generator = check_random_state(random_state) 57 | 58 | if isinstance(centers, numbers.Integral): 59 | centers = generator.uniform(center_box[0], center_box[1], 60 | size=(centers, n_features)) 61 | else: 62 | from sklearn.utils import check_array 63 | centers = check_array(centers) 64 | n_features = centers.shape[1] 65 | 66 | if isinstance(cluster_std, numbers.Real): 67 | cluster_std = np.ones(len(centers)) * cluster_std 68 | 69 | X = [] 70 | y = [] 71 | 72 | n_centers = centers.shape[0] 73 | n_samples_per_center = [int(n_samples // n_centers)] * n_centers 74 | 75 | for i in range(n_samples % n_centers): 76 | n_samples_per_center[i] += 1 77 | 78 | for i, (n, std) in enumerate(zip(n_samples_per_center, cluster_std)): 79 | X.append(centers[i] + generator.normal(scale=std, 80 | size=(n, n_features))) 81 | y += [i] * n 82 | 83 | X = np.concatenate(X) 84 | y = np.array(y) 85 | 86 | if shuffle: 87 | indices = np.arange(n_samples) 88 | generator.shuffle(indices) 89 | X = X[indices] 90 | y = y[indices] 91 | 92 | return X, y 93 | -------------------------------------------------------------------------------- /pyemma/coordinates/data/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r""" 21 | =============================================================================== 22 | data - Data and input/output utilities (:mod:`pyemma.coordinates.data`) 23 | =============================================================================== 24 | 25 | .. currentmodule: pyemma.coordinates.data 26 | 27 | Order parameters 28 | ================ 29 | 30 | .. autosummary:: 31 | :toctree: generated/ 32 | 33 | MDFeaturizer - selects and computes features from MD trajectories 34 | CustomFeature - define arbitrary function to extract features 35 | 36 | Reader 37 | ====== 38 | 39 | .. autosummary:: 40 | :toctree: generated/ 41 | 42 | FeatureReader - reads features via featurizer 43 | NumPyFileReader - reads numpy files 44 | PyCSVReader - reads tabulated ascii files 45 | DataInMemory - used if data is already available in mem 46 | FragmentedTrajectoryReader 47 | 48 | """ 49 | from .feature_reader import FeatureReader 50 | from .featurization.featurizer import MDFeaturizer, CustomFeature 51 | from .data_in_memory import DataInMemory 52 | from .numpy_filereader import NumPyFileReader 53 | from .py_csv_reader import PyCSVReader 54 | from .fragmented_trajectory_reader import FragmentedTrajectoryReader 55 | 56 | # util func 57 | from .util.reader_utils import create_file_reader 58 | -------------------------------------------------------------------------------- /pyemma/coordinates/data/_base/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/data/_base/__init__.py -------------------------------------------------------------------------------- /pyemma/coordinates/data/_base/_in_memory_mixin.py: -------------------------------------------------------------------------------- 1 | 2 | class InMemoryMixin(object): 3 | """ Performs mapping of an iterable/datasource to memory. 4 | """ 5 | 6 | __serialize_version = 0 7 | __serialize_fields = ('_in_memory', '_Y', '_Y_source') 8 | 9 | def __init__(self): 10 | super(InMemoryMixin, self).__init__() 11 | self._in_memory = False 12 | self._mapping_to_mem_active = False 13 | self._Y = None 14 | self._Y_source = None 15 | 16 | @property 17 | def in_memory(self): 18 | r"""are results stored in memory?""" 19 | return self._in_memory 20 | 21 | @in_memory.setter 22 | def in_memory(self, op_in_mem): 23 | r""" 24 | If set to True, the output will be stored in memory. 25 | """ 26 | old_state = self.in_memory 27 | if not old_state and op_in_mem: 28 | self._map_to_memory() 29 | elif not op_in_mem and old_state: 30 | self._clear_in_memory() 31 | 32 | def _clear_in_memory(self): 33 | self._Y = None 34 | self._Y_source = None 35 | self._in_memory = False 36 | 37 | def _map_to_memory(self, stride=1): 38 | r"""Maps results to memory. Will be stored in attribute :attr:`_Y`.""" 39 | self._mapping_to_mem_active = True 40 | try: 41 | self._Y = self.get_output(stride=stride) 42 | from pyemma.coordinates.data import DataInMemory 43 | self._Y_source = DataInMemory(self._Y) 44 | finally: 45 | self._mapping_to_mem_active = False 46 | 47 | self._in_memory = True 48 | -------------------------------------------------------------------------------- /pyemma/coordinates/data/_base/streaming_estimator.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2016 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | 19 | 20 | from pyemma._base.estimator import Estimator 21 | from pyemma.coordinates.data import DataInMemory 22 | from pyemma.coordinates.data._base.iterable import Iterable 23 | from pyemma.util.exceptions import NotConvergedWarning 24 | 25 | 26 | class StreamingEstimator(Estimator): 27 | r""" Base class for streamed estimation. 28 | 29 | It checks the input and wraps it in a Iterable, to be able to access the data 30 | in a streaming fashion. 31 | """ 32 | 33 | def estimate(self, X, chunksize=None, **kwargs): 34 | # ensure the input is able to provide a stream 35 | if not isinstance(X, Iterable): 36 | from pyemma.util import types 37 | array_list = types.ensure_traj_list(X) 38 | X = DataInMemory(array_list, chunksize=chunksize) 39 | # Because we want to use pipelining methods like get_output, we have to set a data producer. 40 | self.data_producer = X 41 | X.chunksize = chunksize 42 | # run estimation 43 | try: 44 | super(StreamingEstimator, self).estimate(X, **kwargs) 45 | except NotConvergedWarning as ncw: 46 | self.logger.info( 47 | "Presumably finished estimation. Message: %s" % ncw) 48 | return self 49 | -------------------------------------------------------------------------------- /pyemma/coordinates/data/featurization/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/data/featurization/__init__.py -------------------------------------------------------------------------------- /pyemma/coordinates/data/featurization/_base.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | ''' 19 | Created on 15.02.2016 20 | 21 | @author: marscher 22 | ''' 23 | from pyemma._base.serialization.serialization import SerializableMixIn 24 | 25 | 26 | class Feature(SerializableMixIn): 27 | __serialize_version = 0 28 | __serialize_fields = ('dimension', 'top') 29 | 30 | @property 31 | def dimension(self): 32 | return self._dim 33 | 34 | @dimension.setter 35 | def dimension(self, val): 36 | self._dim = int(val) 37 | 38 | @property 39 | def top(self): 40 | return self._top 41 | 42 | @top.setter 43 | def top(self, value): 44 | self._top = value 45 | 46 | def describe(self): 47 | raise NotImplementedError() 48 | 49 | def __eq__(self, other): 50 | if not isinstance(other, Feature): 51 | return False 52 | # TODO: here it should be fine to use simply the (quicker) hash func to ensure we have the same topology 53 | # for safety reasons, we use the much slower equality check. 54 | return self.dimension == other.dimension and self.top == other.top 55 | 56 | def __repr__(self): 57 | return str(self.describe()) 58 | 59 | -------------------------------------------------------------------------------- /pyemma/coordinates/data/util/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | -------------------------------------------------------------------------------- /pyemma/coordinates/estimation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/estimation/__init__.py -------------------------------------------------------------------------------- /pyemma/coordinates/tests/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_001-033.xtc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_001-033.xtc -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_034-066.xtc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_034-066.xtc -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_067-100.xtc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_067-100.xtc -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.binpos: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.binpos -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.dcd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.dcd -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.h5 -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.lh5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.lh5 -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.nc -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.netcdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.netcdf -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.trr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.trr -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/bpti_mini.xtc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/bpti_mini.xtc -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/opsin_Ca_1_frame.pdb.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/opsin_Ca_1_frame.pdb.gz -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/opsin_aa_1_frame.pdb.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/opsin_aa_1_frame.pdb.gz -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/test.pdb: -------------------------------------------------------------------------------- 1 | ATOM 3 CH3 ACE A 1 28.490 31.600 33.379 0.00 1.00 2 | ATOM 7 C ACE A 2 27.760 30.640 34.299 0.00 1.00 3 | ATOM 8 C ACE A 2 27.760 30.640 34.299 0.00 1.00 4 | 5 | -------------------------------------------------------------------------------- /pyemma/coordinates/tests/data/test_data_koopman.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/coordinates/tests/data/test_data_koopman.npz -------------------------------------------------------------------------------- /pyemma/coordinates/tests/test_acf.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | 21 | import unittest 22 | import numpy as np 23 | 24 | from pyemma.coordinates.acf import acf 25 | 26 | 27 | 28 | class TestACF(unittest.TestCase): 29 | def test(self): 30 | # generate some data 31 | data = np.random.rand(100, 3) 32 | 33 | testacf = acf(data) 34 | 35 | # direct computation of acf (single trajectory, three observables) 36 | N = data.shape[0] 37 | refacf = np.zeros(data.shape) 38 | meanfree = data - np.mean(data, axis=0) 39 | padded = np.concatenate((meanfree, np.zeros(data.shape)), axis=0) 40 | for tau in range(N): 41 | refacf[tau] = (padded[0:N, :]*padded[tau:N+tau, :]).sum(axis=0)/(N-tau) 42 | refacf /= refacf[0] # normalize 43 | 44 | np.testing.assert_allclose(refacf, testacf) 45 | 46 | if __name__ == "__main__": 47 | unittest.main() 48 | -------------------------------------------------------------------------------- /pyemma/coordinates/tests/test_h5reader.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | import h5py 4 | 5 | from pyemma.coordinates.data.h5_reader import H5Reader 6 | from pyemma.util.testing_tools import MockLoggingHandler 7 | from pyemma.coordinates import source 8 | 9 | 10 | class TestH5Reader(unittest.TestCase): 11 | @classmethod 12 | def setUpClass(cls): 13 | import tempfile 14 | # create test data sets 15 | cls.directory = tempfile.mkdtemp('test_h5reader') 16 | 17 | cls.f1 = tempfile.mktemp(suffix='.h5', dir=cls.directory) 18 | cls.shape = (10, 3) 19 | cls.data = np.arange(cls.shape[0]*cls.shape[1]).reshape(cls.shape) 20 | with h5py.File(cls.f1, mode='w') as f: 21 | ds = f.create_group('test').create_group('another_group').create_dataset('test_ds', shape=cls.shape) 22 | ds[:] = cls.data 23 | ds = f.create_group('test2').create_dataset('test_ds', shape=cls.shape) 24 | ds[:] = cls.data 25 | f.create_dataset('another_ds', shape=(10, 23)) 26 | f.create_dataset('1d', data=np.arange(10)) 27 | f.create_dataset('5d', data=np.arange(25).reshape(5, 5)) 28 | cls.total_frames = cls.shape[0] * 2 29 | 30 | cls.reader = H5Reader(cls.f1, selection='/.*/test_ds') 31 | 32 | @classmethod 33 | def tearDownClass(cls): 34 | import shutil 35 | shutil.rmtree(cls.directory) 36 | 37 | def test_ndim(self): 38 | assert self.reader.ndim == self.shape[1] 39 | assert self.reader.filenames == [self.f1] 40 | self.assertEqual(self.reader.n_frames_total(), self.total_frames) 41 | self.assertEqual(self.reader.n_datasets, 2) 42 | 43 | def test_udpate_selection(self): 44 | self.reader.selection = '/test2/*' 45 | assert self.reader.ndim == self.shape[1] 46 | assert self.reader.n_frames_total() == self.shape[0] 47 | assert self.reader.n_datasets == 1 48 | 49 | def test_non_matching_selection(self): 50 | with self.assertRaises(ValueError): 51 | h = MockLoggingHandler() 52 | import logging 53 | logging.getLogger('pyemma.coordinates').addHandler(h) 54 | r = H5Reader(self.f1, selection='/non_existent') 55 | 56 | self.assertIn('did not match', h.messages['warning']) 57 | assert r.ndim == -1 58 | assert r.n_frames_total() == 0 59 | assert r.ntraj == 0 60 | 61 | def test_output(self): 62 | out = self.reader.get_output() 63 | np.testing.assert_equal(out, [self.data]*2) 64 | 65 | def test_source(self): 66 | reader = source(self.f1, selection='/.*/test_ds') 67 | self.assertIsInstance(reader, H5Reader) 68 | self.assertEqual(reader.ntraj, 2) 69 | 70 | def test_1d(self): 71 | reader = source(self.f1, selection='/1d') 72 | out = reader.get_output()[0] 73 | assert out.shape[0] == 10 74 | assert out.shape[1] == 1 75 | 76 | def test_5d(self): 77 | reader = source(self.f1, selection='/5d') 78 | out = reader.get_output()[0] 79 | assert out.shape[0] == 5 80 | assert out.shape[1] == 5 81 | 82 | if __name__ == '__main__': 83 | unittest.main() 84 | -------------------------------------------------------------------------------- /pyemma/coordinates/tests/test_sources_merger.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import pkg_resources 3 | import os 4 | from glob import glob 5 | import numpy as np 6 | 7 | from pyemma.coordinates import source, tica 8 | from pyemma.coordinates.data.sources_merger import SourcesMerger 9 | 10 | 11 | class TestSourcesMerger(unittest.TestCase): 12 | 13 | def setUp(self): 14 | self.readers = [] 15 | data_dir = pkg_resources.resource_filename('pyemma.coordinates.tests', 'data') 16 | # three md trajs 17 | trajs = glob(data_dir + "/bpti_0*.xtc") 18 | top = os.path.join(data_dir, 'bpti_ca.pdb') 19 | self.readers.append(source(trajs, top=top)) 20 | self.readers[0].featurizer.add_all() 21 | ndim = self.readers[0].ndim 22 | # three random arrays 23 | lengths = self.readers[0].trajectory_lengths() 24 | arrays = [np.random.random( (length, ndim) ) for length in lengths] 25 | self.readers.append(source(arrays)) 26 | 27 | self.readers.append(tica(self.readers[-1], dim=20)) 28 | 29 | def _get_output_compare(self, joiner, stride=1, chunk=0, skip=0): 30 | out = joiner.get_output(stride=stride, chunk=chunk, skip=skip) 31 | assert len(out) == 3 # 3 trajs 32 | assert joiner.ndim == sum(r.dimension() for r in self.readers) 33 | np.testing.assert_equal(joiner.trajectory_lengths(), self.readers[0].trajectory_lengths()) 34 | 35 | from collections import defaultdict 36 | outs = defaultdict(list) 37 | for r in self.readers: 38 | for i, x in enumerate(r.get_output(stride=stride, chunk=chunk, skip=skip)): 39 | outs[i].append(x) 40 | combined = [np.hstack(outs[i]).astype(np.float32) for i in range(3)] 41 | np.testing.assert_equal([o.astype(np.float32) for o in out], combined) 42 | 43 | def test_combined_output(self): 44 | j = SourcesMerger(self.readers) 45 | self._get_output_compare(j, stride=1, chunk=0, skip=0) 46 | self._get_output_compare(j, stride=2, chunk=1, skip=0) 47 | self._get_output_compare(j, stride=3, chunk=2, skip=7) 48 | self._get_output_compare(j, stride=5, chunk=9, skip=3) 49 | 50 | def test_ra_stride(self): 51 | ra_indices = np.array([[0,7], [0, 23], [1, 30], [2, 9]]) 52 | j = SourcesMerger(self.readers) 53 | self._get_output_compare(j, stride=ra_indices) 54 | 55 | def test_non_matching_lengths(self): 56 | data = self.readers[1].data 57 | data = [data[0], data[1], data[2][:20]] 58 | self.readers.append(source(data)) 59 | with self.assertRaises(ValueError) as ctx: 60 | SourcesMerger(self.readers) 61 | self.assertIn('matching', ctx.exception.args[0]) 62 | 63 | def test_fragmented_trajs(self): 64 | """ build two fragmented readers consisting out of two fragments each and check if they are merged properly.""" 65 | segment_0 = np.arange(20) 66 | segment_1 = np.arange(20, 40) 67 | 68 | s1 = source([(segment_0, segment_1)]) 69 | s2 = source([(segment_0, segment_1)]) 70 | 71 | sm = SourcesMerger((s1, s2)) 72 | 73 | out = sm.get_output() 74 | x = np.atleast_2d(np.arange(40)) 75 | expected = [np.concatenate((x, x), axis=0).T] 76 | 77 | np.testing.assert_equal(out, expected) 78 | -------------------------------------------------------------------------------- /pyemma/coordinates/tests/test_streaming_transformer.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | from pyemma.coordinates import source 4 | from pyemma.coordinates.data._base.transformer import StreamingTransformer 5 | 6 | 7 | class MyTransformer(StreamingTransformer): 8 | def _transform_array(self, array): 9 | return array * 2 10 | 11 | def describe(self, *args, **kwargs): 12 | return () 13 | 14 | def dimension(self): 15 | return 1 16 | 17 | 18 | class TestStreamingTransformer(unittest.TestCase): 19 | def test_get_output(self): 20 | data = np.ones(10) 21 | t = MyTransformer() 22 | t.data_producer = source(data) 23 | out = t.get_output() 24 | np.testing.assert_equal(out[0].squeeze(), data*2) 25 | -------------------------------------------------------------------------------- /pyemma/coordinates/tests/util.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | import tempfile 5 | import numpy as np 6 | import mdtraj 7 | import pkg_resources 8 | 9 | 10 | def get_top(): 11 | return pkg_resources.resource_filename(__name__, 'data/test.pdb') 12 | 13 | 14 | def create_traj(top=None, format='.xtc', dir=None, length=1000, start=0): 15 | trajfile = tempfile.mktemp(suffix=format, dir=dir) 16 | xyz = np.arange(start * 3 * 3, (start + length) * 3 * 3) 17 | xyz = xyz.reshape((-1, 3, 3)) 18 | if top is None: 19 | top = get_top() 20 | 21 | t = mdtraj.load(top) 22 | t.xyz = xyz 23 | t.unitcell_vectors = np.array(length * [[0, 0, 1], [0, 1, 0], [1, 0, 0]]).reshape(length, 3, 3) 24 | t.time = np.arange(length) 25 | t.save(trajfile) 26 | 27 | return trajfile, xyz, length 28 | 29 | 30 | def create_trajectory_csv(dirname, data): 31 | fname = tempfile.mktemp(suffix='.csv.dat', dir=dirname) 32 | np.savetxt(fname, data) 33 | return fname 34 | 35 | 36 | def create_trajectory_numpy(dirname, data): 37 | fname = tempfile.mktemp(suffix='.npy', dir=dirname) 38 | np.save(fname, data) 39 | return fname 40 | 41 | 42 | def create_dummy_pdb(dirname, dims): 43 | dummy_pdb = tempfile.mktemp('.pdb', dir=dirname) 44 | with open(dummy_pdb, 'w') as f: 45 | for i in range(dims): 46 | print('ATOM %5d C ACE A 1 28.490 31.600 33.379 0.00 1.00' % i, file=f) 47 | return dummy_pdb 48 | 49 | 50 | def create_trajectory_trr(dims, dirname, data): 51 | from mdtraj.core.trajectory import TRRTrajectoryFile 52 | fname = tempfile.mktemp(suffix='.trr', dir=dirname) 53 | 54 | with TRRTrajectoryFile(fname, 'w') as f: 55 | f.write(data.reshape(-1, dims, 3)) 56 | 57 | return fname 58 | 59 | 60 | def create_trajectory_xtc(dims, dirname, data): 61 | from mdtraj.core.trajectory import XTCTrajectoryFile 62 | fname = tempfile.mktemp(suffix='.xtc', dir=dirname) 63 | 64 | shaped = data.reshape(-1, dims, 3) 65 | with XTCTrajectoryFile(fname, 'w') as f: 66 | f.write(shaped) 67 | 68 | return fname 69 | 70 | 71 | def create_trajectory_h5(dims, dirname, data): 72 | import h5py 73 | fname = tempfile.mktemp(suffix='.h5', dir=dirname) 74 | 75 | with h5py.File(fname, mode='w') as f: 76 | f.create_dataset('somedata', data=data.reshape(-1, dims, 3)) 77 | 78 | return fname 79 | 80 | def create_trajectory_dcd(dims, dirname, data): 81 | from mdtraj.core.trajectory import DCDTrajectoryFile 82 | 83 | fname = tempfile.mktemp(suffix='.dcd', dir=dirname) 84 | shaped = data.reshape(-1, dims, 3) 85 | with DCDTrajectoryFile(fname, 'w') as f: 86 | f.write(shaped * 10) # unit Angstroems is assumed by mdtraj. 87 | return fname 88 | 89 | 90 | def create_transform(reader): 91 | from pyemma.coordinates.data._base.transformer import StreamingTransformer 92 | 93 | class IdentityTransform(StreamingTransformer): 94 | def dimension(self): 95 | return reader.ndim 96 | def describe(self): 97 | return 'identity' 98 | def _transform_array(self, X): 99 | return X 100 | 101 | t = IdentityTransform() 102 | t.data_producer = reader 103 | 104 | return t 105 | -------------------------------------------------------------------------------- /pyemma/coordinates/transform/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r""" 21 | =============================================================================== 22 | transform - Transformation Utilities (:mod:`pyemma.coordinates.transform`) 23 | =============================================================================== 24 | .. currentmodule:: pyemma.coordinates.transform 25 | 26 | .. autosummary:: 27 | :toctree: generated/ 28 | 29 | PCA - principal components 30 | TICA - time independent components 31 | VAMP - Variational approach for Markov processes 32 | VAMPModel - Kinetic model form the Variational approach for Markov processes 33 | VAMPChapmanKolmogorovValidator - Chapman Kolmogorov test for the Variational approach for Markov processes 34 | """ 35 | 36 | from .pca import * 37 | from .tica import * 38 | from .nystroem_tica import * 39 | from .vamp import * 40 | -------------------------------------------------------------------------------- /pyemma/coordinates/util/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | -------------------------------------------------------------------------------- /pyemma/coordinates/util/stat.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | 21 | import numpy as np 22 | from pyemma.util.annotators import deprecated 23 | 24 | 25 | __author__ = 'Fabian Paul' 26 | __all__ = ['histogram'] 27 | 28 | 29 | @deprecated("Please use pyemma.coordinates.histogram()") 30 | def hist(transform, dimensions, nbins): 31 | return histogram(transform, dimensions, nbins) 32 | 33 | 34 | def histogram(transform, dimensions, nbins): 35 | '''Computes the N-dimensional histogram of the transformed data. 36 | 37 | Parameters 38 | ---------- 39 | transform : pyemma.coordinates.transfrom.Transformer object 40 | transform that provides the input data 41 | dimensions : tuple of indices 42 | indices of the dimensions you want to examine 43 | nbins : tuple of ints 44 | number of bins along each dimension 45 | 46 | Returns 47 | ------- 48 | counts : (bins[0],bins[1],...) ndarray of ints 49 | counts compatible with pyplot.pcolormesh and pyplot.bar 50 | edges : list of (bins[i]) ndarrays 51 | bin edges compatible with pyplot.pcolormesh and pyplot.bar, 52 | see below. 53 | 54 | Examples 55 | -------- 56 | 57 | >>> import matplotlib.pyplot as plt # doctest: +SKIP 58 | 59 | Only for ipython notebook 60 | >> %matplotlib inline # doctest: +SKIP 61 | 62 | >>> counts, edges=histogram(transform, dimensions=(0,1), nbins=(20, 30)) # doctest: +SKIP 63 | >>> plt.pcolormesh(edges[0], edges[1], counts.T) # doctest: +SKIP 64 | 65 | >>> counts, edges=histogram(transform, dimensions=(1,), nbins=(50,)) # doctest: +SKIP 66 | >>> plt.bar(edges[0][:-1], counts, width=edges[0][1:]-edges[0][:-1]) # doctest: +SKIP 67 | ''' 68 | maximum = np.ones(len(dimensions)) * (-np.inf) 69 | minimum = np.ones(len(dimensions)) * np.inf 70 | # compute min and max 71 | for _, chunk in transform: 72 | maximum = np.max( 73 | np.vstack(( 74 | maximum, 75 | np.max(chunk[:, dimensions], axis=0))), 76 | axis=0) 77 | minimum = np.min( 78 | np.vstack(( 79 | minimum, 80 | np.min(chunk[:, dimensions], axis=0))), 81 | axis=0) 82 | # define bins 83 | bins = [np.linspace(m, M, num=n) 84 | for m, M, n in zip(minimum, maximum, nbins)] 85 | res = np.zeros(np.array(nbins) - 1) 86 | # compute actual histogram 87 | for _, chunk in transform: 88 | part, _ = np.histogramdd(chunk[:, dimensions], bins=bins) 89 | res += part 90 | return res, bins 91 | -------------------------------------------------------------------------------- /pyemma/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | __author__ = 'noe' 20 | 21 | from .api import * 22 | -------------------------------------------------------------------------------- /pyemma/datasets/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/datasets/tests/__init__.py -------------------------------------------------------------------------------- /pyemma/logging.yml: -------------------------------------------------------------------------------- 1 | # PyEMMA's default logging settings 2 | # If you want to enable file logging, uncomment the file related handlers and handlers 3 | # 4 | 5 | # do not disable other loggers by default. 6 | disable_existing_loggers: False 7 | 8 | # please do not change version, it is an internal variable used by Python. 9 | version: 1 10 | 11 | formatters: 12 | simpleFormater: 13 | format: '%(asctime)s %(name)-12s %(levelname)-8s %(message)s' 14 | datefmt: '%d-%m-%y %H:%M:%S' 15 | 16 | handlers: 17 | # log to stdout 18 | console: 19 | class: logging.StreamHandler 20 | formatter: simpleFormater 21 | stream: ext://sys.stdout 22 | # example for rotating log files, disabled by default 23 | #rotating_files: 24 | # class: logging.handlers.RotatingFileHandler 25 | # formatter: simpleFormater 26 | # filename: pyemma.log 27 | # maxBytes: 1048576 # 1 MB 28 | # backupCount: 3 29 | 30 | loggers: 31 | pyemma: 32 | level: INFO 33 | # by default no file logging! 34 | handlers: [console] #, rotating_files] 35 | 36 | -------------------------------------------------------------------------------- /pyemma/msm/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r""" 21 | 22 | .. currentmodule:: pyemma.msm 23 | 24 | User Functions 25 | ============== 26 | For most users, the following high-level functions are sufficient to estimate msm models from data. 27 | Expert users may want to construct Estimators or Models (see below) directly. 28 | 29 | .. autosummary:: 30 | :toctree: generated/ 31 | 32 | markov_model 33 | timescales_msm 34 | its 35 | estimate_markov_model 36 | bayesian_markov_model 37 | tpt 38 | timescales_hmsm 39 | estimate_hidden_markov_model 40 | bayesian_hidden_markov_model 41 | 42 | MSM classes 43 | =========== 44 | 45 | **Estimators** to generate models from data. If you are not an expert user, 46 | use the API functions above. 47 | 48 | .. autosummary:: 49 | :toctree: generated/ 50 | 51 | ImpliedTimescales 52 | ChapmanKolmogorovValidator 53 | MaximumLikelihoodMSM 54 | BayesianMSM 55 | OOMReweightedMSM 56 | MaximumLikelihoodHMSM 57 | BayesianHMSM 58 | 59 | 60 | **Models** of the kinetics or stationary properties of the data. 61 | If you are not an expert user, use the API functions above. 62 | 63 | .. autosummary:: 64 | :toctree: generated/ 65 | 66 | MSM 67 | SampledMSM 68 | HMSM 69 | SampledHMSM 70 | ReactiveFlux 71 | PCCA 72 | 73 | """ 74 | 75 | from .models import MSM, HMSM, SampledMSM, SampledHMSM, ReactiveFlux, PCCA 76 | 77 | from .estimators import AugmentedMarkovModel, OOMReweightedMSM 78 | from .estimators import ChapmanKolmogorovValidator 79 | from .estimators import ImpliedTimescales 80 | from .estimators import MaximumLikelihoodHMSM, BayesianHMSM 81 | from .estimators import MaximumLikelihoodMSM, BayesianMSM 82 | 83 | # high-level api 84 | from .api import * 85 | -------------------------------------------------------------------------------- /pyemma/msm/estimators/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | __author__ = 'noe' 20 | 21 | from .maximum_likelihood_msm import MaximumLikelihoodMSM 22 | from .oom_reweighted_msm import OOMReweightedMSM 23 | from .augmented_msm import AugmentedMarkovModel 24 | from .bayesian_msm import BayesianMSM 25 | from .maximum_likelihood_hmsm import MaximumLikelihoodHMSM 26 | from .bayesian_hmsm import BayesianHMSM 27 | from .implied_timescales import ImpliedTimescales 28 | from .lagged_model_validators import ChapmanKolmogorovValidator, EigenvalueDecayValidator 29 | -------------------------------------------------------------------------------- /pyemma/msm/models/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | __author__ = 'noe' 20 | 21 | from .msm import MSM 22 | from .msm_sampled import SampledMSM 23 | from .hmsm import HMSM 24 | from .hmsm_sampled import SampledHMSM 25 | from .reactive_flux import ReactiveFlux 26 | from .pcca import PCCA 27 | -------------------------------------------------------------------------------- /pyemma/msm/models/hmsm_sampled.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r"""Implement a MSM class that builds a Markov state models from 21 | microstate trajectories, automatically computes important properties 22 | and provides them for later access. 23 | 24 | .. moduleauthor:: F. Noe 25 | 26 | """ 27 | 28 | 29 | from pyemma._base.model import SampledModel as _SampledModel 30 | from pyemma.msm.models.hmsm import HMSM as _HMSM 31 | from pyemma.util.types import is_iterable 32 | 33 | 34 | class SampledHMSM(_HMSM, _SampledModel): 35 | r""" Sampled Hidden Markov state model """ 36 | 37 | __serialize_version = 0 38 | 39 | # TODO: maybe rename to parametrize in order to avoid confusion with set_params that has a different behavior? 40 | def set_model_params(self, samples=None, conf=0.95, 41 | P=None, pobs=None, pi=None, reversible=None, dt_model='1 step', neig=None): 42 | """ 43 | 44 | Parameters 45 | ---------- 46 | samples : list of MSM objects 47 | sampled MSMs 48 | conf : float, optional, default=0.68 49 | Confidence interval. By default one-sigma (68.3%) is used. Use 95.4% for two sigma or 99.7% for three sigma. 50 | 51 | """ 52 | # set model parameters of superclass 53 | _SampledModel.set_model_params(self, samples=samples, conf=conf) 54 | _HMSM.set_model_params(self, P=P, pobs=pobs, pi=pi, reversible=reversible, dt_model=dt_model, neig=neig) 55 | 56 | def submodel(self, states=None, obs=None): 57 | """Returns a HMM with restricted state space 58 | 59 | Parameters 60 | ---------- 61 | states : None or int-array 62 | Hidden states to restrict the model to (if not None). 63 | obs : None, str or int-array 64 | Observed states to restrict the model to (if not None). 65 | 66 | Returns 67 | ------- 68 | hmm : HMM 69 | The restricted HMM. 70 | 71 | """ 72 | # get the reference HMM submodel 73 | ref = super(SampledHMSM, self).submodel(states=states, obs=obs) 74 | # get the sample submodels 75 | samples_sub = [sample.submodel(states=states, obs=obs) for sample in self.samples] 76 | # new model 77 | return SampledHMSM(samples_sub, ref=ref, conf=self.conf) 78 | -------------------------------------------------------------------------------- /pyemma/msm/models/msm_sampled.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | from pyemma._base.model import SampledModel 20 | from pyemma.msm.models.msm import MSM 21 | 22 | __author__ = 'noe' 23 | 24 | 25 | class SampledMSM(MSM, SampledModel): 26 | r""" Sampled Markov state model """ 27 | 28 | __serialize_version = 0 29 | 30 | # TODO: maybe rename to parametrize in order to avoid confusion with set_params that has a different behavior? 31 | def set_model_params(self, samples=None, conf=0.95, 32 | P=None, pi=None, reversible=None, dt_model='1 step', neig=None): 33 | """ 34 | 35 | Parameters 36 | ---------- 37 | samples : list of MSM objects 38 | sampled MSMs 39 | conf : float, optional, default=0.68 40 | Confidence interval. By default one-sigma (68.3%) is used. Use 95.4% for two sigma or 99.7% for three sigma. 41 | 42 | """ 43 | # set model parameters of superclass 44 | SampledModel.set_model_params(self, samples=samples, conf=conf) 45 | MSM.set_model_params(self, P=P, pi=pi, reversible=reversible, dt_model=dt_model, neig=neig) 46 | -------------------------------------------------------------------------------- /pyemma/msm/models/pcca.py: -------------------------------------------------------------------------------- 1 | from deeptime.markov import PCCAModel, pcca 2 | 3 | from pyemma._base.serialization.serialization import SerializableMixIn 4 | 5 | 6 | class PCCA(PCCAModel, SerializableMixIn): 7 | __serialize_version = 1 8 | 9 | """ 10 | PCCA+ spectral clustering method with optimized memberships [1]_ 11 | Clusters the first m eigenvectors of a transition matrix in order to cluster the states. 12 | This function does not assume that the transition matrix is fully connected. Disconnected sets 13 | will automatically define the first metastable states, with perfect membership assignments. 14 | 15 | Parameters 16 | ---------- 17 | P : ndarray (n,n) 18 | Transition matrix. 19 | m : int 20 | Number of clusters to group to. 21 | 22 | References 23 | ---------- 24 | [1] S. Roeblitz and M. Weber, Fuzzy spectral clustering by PCCA+: 25 | application to Markov state models and data classification. 26 | Adv Data Anal Classif 7, 147-179 (2013). 27 | [2] F. Noe, multiset PCCA and HMMs, in preparation. 28 | [3] F. Noe, H. Wu, J.-H. Prinz and N. Plattner: 29 | Projected and hidden Markov models for calculating kinetics and metastable states of complex molecules 30 | J. Chem. Phys. 139, 184114 (2013) 31 | """ 32 | def __init__(self, P, m): 33 | dt_pcca = pcca(P, m) 34 | super(PCCA, self).__init__(transition_matrix_coarse=dt_pcca.coarse_grained_transition_matrix, 35 | pi_coarse=dt_pcca.coarse_grained_stationary_probability, 36 | memberships=dt_pcca.memberships, 37 | metastable_distributions=dt_pcca.metastable_distributions) 38 | self.P = P 39 | 40 | @property 41 | def transition_matrix(self): 42 | return self.P 43 | 44 | @property 45 | def stationary_probability(self): 46 | return self.coarse_grained_stationary_probability 47 | 48 | @property 49 | def output_probabilities(self): 50 | return self.metastable_distributions 51 | 52 | @property 53 | def metastable_sets(self): 54 | return self.sets 55 | 56 | @property 57 | def metastable_assignment(self): 58 | return self.assignments 59 | -------------------------------------------------------------------------------- /pyemma/msm/tests/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | -------------------------------------------------------------------------------- /pyemma/msm/tests/data/TestData_ITS_OOM.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/msm/tests/data/TestData_ITS_OOM.npz -------------------------------------------------------------------------------- /pyemma/msm/tests/data/TestData_OOM_MSM.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/msm/tests/data/TestData_OOM_MSM.npz -------------------------------------------------------------------------------- /pyemma/msm/tests/test_dtraj_stats.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import numpy as np 4 | from deeptime.decomposition import cvsplit_trajs 5 | from deeptime.decomposition._score import blocksplit_trajs 6 | from deeptime.markov.tools.estimation import count_matrix 7 | 8 | from pyemma.msm.estimators._dtraj_stats import DiscreteTrajectoryStats 9 | from pyemma.util.types import ensure_dtraj_list 10 | 11 | 12 | class TestDtrajStats(unittest.TestCase): 13 | 14 | def test_blocksplit_dtrajs_sliding(self): 15 | dtrajs = [np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), np.array([0, 1, 9, 10])] 16 | for lag in range(1, 10): 17 | dtrajs_new = blocksplit_trajs(dtrajs, blocksize=lag, sliding=True) 18 | C1 = count_matrix(dtrajs, lag, sliding=True, nstates=11).toarray() 19 | C2 = count_matrix(dtrajs_new, lag, sliding=True, nstates=11).toarray() 20 | assert np.all(C1 == C2) 21 | 22 | def test_blocksplit_dtrajs_sampling(self): 23 | dtrajs = [np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), np.array([0, 1, 9, 10])] 24 | for lag in range(1, 10): 25 | dtrajs_new = blocksplit_trajs(dtrajs, blocksize=lag, sliding=False, shift=0) 26 | C1 = count_matrix(dtrajs, lag, sliding=False, nstates=11).toarray() 27 | C2 = count_matrix(dtrajs_new, lag, sliding=False, nstates=11).toarray() 28 | assert np.all(C1 == C2) 29 | 30 | def test_blocksplit_dtrajs_cvsplit(self): 31 | dtrajs = [np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), np.array([0, 1, 9, 10])] 32 | for lag in range(1, 5): 33 | dtrajs_new = blocksplit_trajs(dtrajs, blocksize=lag, sliding=False, shift=0) 34 | dtrajs_train, dtrajs_test = cvsplit_trajs(dtrajs_new) 35 | dtrajs_train = ensure_dtraj_list(dtrajs_train) 36 | dtrajs_test = ensure_dtraj_list(dtrajs_test) 37 | assert len(dtrajs_train) > 0 38 | assert len(dtrajs_test) > 0 39 | 40 | def test_mincount_connectivity(self): 41 | dtrajs = np.zeros(10, dtype=int) 42 | dtrajs[0] = 1 43 | dtrajs[-1] = 1 44 | dts = DiscreteTrajectoryStats(dtrajs) 45 | 46 | dts.count_lagged(1, mincount_connectivity=0) 47 | 48 | C_mincount0 = dts.count_matrix_largest.todense() 49 | 50 | np.testing.assert_equal(C_mincount0, np.array([[7, 1], [1, 0]])) 51 | 52 | dts.count_lagged(1, mincount_connectivity=2) 53 | C = np.array(dts.count_matrix_largest.todense()) 54 | np.testing.assert_equal(C, np.array([[7]])) 55 | 56 | # check that the original count matrix remains unmodified 57 | np.testing.assert_equal(dts.count_matrix().todense(), C_mincount0) 58 | 59 | 60 | if __name__ == '__main__': 61 | unittest.main() 62 | -------------------------------------------------------------------------------- /pyemma/msm/tests/test_subset.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from pyemma.msm.util.subset import add_full_state_methods, map_to_full_state, SubSet 4 | import numpy as np 5 | 6 | import types 7 | 8 | k_global = 3 9 | 10 | 11 | @add_full_state_methods 12 | class test_class(SubSet): 13 | def __init__(self, active_set=(2, 3, 4), nstates_full=10): 14 | self.active_set = active_set 15 | self.nstates_full = nstates_full 16 | 17 | @map_to_full_state(default_arg=np.inf) 18 | def right_eigenvectors(self): 19 | return np.arange(27).reshape(-1, 3) 20 | 21 | @map_to_full_state(default_arg=np.inf, extend_along_axis=1) 22 | def left_eigenvectors(self): 23 | return np.arange(27).reshape(-1, 3).T 24 | 25 | @map_to_full_state(default_arg=-1) 26 | @property 27 | def test_property(self): 28 | return [4, 5, 6] 29 | 30 | 31 | class TestSubset(unittest.TestCase): 32 | def test_has_member(self): 33 | inst = test_class() 34 | assert hasattr(inst, 'left_eigenvectors_full_state') 35 | assert hasattr(test_class, 'left_eigenvectors_full_state') 36 | assert hasattr(inst, 'test_property_full_state') 37 | assert hasattr(test_class, 'test_property_full_state') 38 | self.assertIsInstance(inst.left_eigenvectors_full_state, types.MethodType) 39 | 40 | def test_property(self): 41 | inst = test_class() 42 | expected = np.ones(inst.nstates_full)*-1 43 | expected[inst.active_set] = inst.test_property 44 | np.testing.assert_equal(inst.test_property_full_state, expected) 45 | self.assertIsInstance(test_class.test_property_full_state, property) 46 | 47 | def test_shape_left_ev(self): 48 | inst = test_class(np.arange(start=23, stop=32), nstates_full=60) 49 | shape = inst.left_eigenvectors().shape 50 | result = inst.left_eigenvectors_full_state() 51 | expected = np.array([np.inf] * shape[0] * inst.nstates_full).reshape(shape[0], -1) 52 | expected[:, inst.active_set] = inst.left_eigenvectors() 53 | np.testing.assert_equal(expected, result) 54 | 55 | def test_shape_right_ev(self): 56 | inst = test_class(np.arange(start=3, stop=12), nstates_full=60) 57 | shape = inst.right_eigenvectors().shape 58 | result = inst.right_eigenvectors_full_state() 59 | expected = np.array([np.inf] * inst.nstates_full * shape[1]).reshape(-1, shape[1]) 60 | expected[inst.active_set, :] = inst.right_eigenvectors() 61 | np.testing.assert_equal(expected, result) 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | 66 | -------------------------------------------------------------------------------- /pyemma/msm/tests/test_tpt.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r"""Unit test for the tpt-function 21 | 22 | .. moduleauthor:: F.Noe 23 | .. moduleauthor:: B.Trendelkamp-Schroer 24 | 25 | """ 26 | 27 | import numpy as np 28 | from deeptime.markov.tools.analysis import mfpt 29 | 30 | from pyemma.msm import estimate_markov_model, tpt 31 | from pyemma.util.numeric import assert_allclose 32 | 33 | 34 | def test_time_units(): 35 | dtraj = np.random.randint(0, 4, 1000) 36 | tau = 12 37 | dt = 0.456 38 | msmobj = estimate_markov_model(dtraj, lag=tau, dt_traj='%f ns' % dt) 39 | 40 | # check MFPT consistency 41 | mfpt_ref = msmobj.mfpt([0], [1]) 42 | tptobj = tpt(msmobj, [0], [1]) 43 | assert_allclose(tptobj.mfpt, mfpt_ref) 44 | assert_allclose(mfpt(msmobj.P, [1], [0], tau=tau) * dt, mfpt_ref) 45 | assert_allclose(np.dot(msmobj.stationary_distribution, tptobj.backward_committor) / tptobj.total_flux, mfpt_ref) 46 | 47 | # check flux consistency 48 | total_flux_ref = tptobj.total_flux 49 | A = tptobj.A 50 | B = tptobj.B 51 | I = tptobj.I 52 | assert_allclose(tptobj.gross_flux[A, :][:, B].sum() + tptobj.gross_flux[A, :][:, I].sum(), 53 | total_flux_ref) 54 | assert_allclose(tptobj.net_flux[A, :][:, B].sum() + tptobj.net_flux[A, :][:, I].sum(), total_flux_ref) 55 | assert_allclose(tptobj.flux[A, :][:, B].sum() + tptobj.flux[A, :][:, I].sum(), total_flux_ref) 56 | mf = tptobj.major_flux(1.0) 57 | assert_allclose(mf[A, :][:, B].sum() + mf[A, :][:, I].sum(), total_flux_ref) 58 | 59 | # check that the coarse-grained version is consistent too 60 | _, tptobj2 = tptobj.coarse_grain([A, I, B]) 61 | assert_allclose(tptobj2.total_flux, total_flux_ref) 62 | assert_allclose(tptobj2.mfpt, mfpt_ref) 63 | -------------------------------------------------------------------------------- /pyemma/msm/util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/msm/util/__init__.py -------------------------------------------------------------------------------- /pyemma/plots/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2014-2018 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | r""" 21 | 22 | ============================================ 23 | plots - Plotting tools (:mod:`pyemma.plots`) 24 | ============================================ 25 | 26 | .. currentmodule:: pyemma.plots 27 | 28 | User-API 29 | ======== 30 | 31 | **Graph plots** 32 | 33 | .. autosummary:: 34 | :toctree: generated/ 35 | 36 | plot_implied_timescales 37 | plot_cktest 38 | 39 | **Contour plots** 40 | 41 | .. autosummary:: 42 | :toctree: generated/ 43 | 44 | plot_density 45 | plot_free_energy 46 | plot_contour 47 | plot_state_map 48 | scatter_contour 49 | 50 | **Network plots** 51 | 52 | .. autosummary:: 53 | :toctree: generated/ 54 | 55 | plot_markov_model 56 | plot_flux 57 | plot_network 58 | 59 | Classes 60 | ======== 61 | 62 | .. autosummary:: 63 | :toctree: generated/ 64 | 65 | NetworkPlot 66 | 67 | """ 68 | from .timescales import plot_implied_timescales 69 | from .plots2d import contour, scatter_contour 70 | from .plots2d import plot_density 71 | from .plots2d import plot_free_energy 72 | from .plots2d import plot_contour 73 | from .plots2d import plot_state_map 74 | from .networks import plot_markov_model, plot_flux, plot_network, NetworkPlot 75 | from .markovtests import plot_cktest 76 | from .thermoplots import * 77 | from .plots1d import plot_feature_histograms 78 | -------------------------------------------------------------------------------- /pyemma/plots/_ext/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/plots/_ext/__init__.py -------------------------------------------------------------------------------- /pyemma/plots/tests/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | def teardown_module(): 21 | # close all figures 22 | import matplotlib.pylab as plt 23 | plt.close('all') 24 | -------------------------------------------------------------------------------- /pyemma/plots/tests/test_its.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | ''' 20 | Created on 10.03.2016 21 | 22 | @author: gph82 23 | ''' 24 | 25 | import unittest 26 | import numpy as np 27 | from deeptime.markov.msm import MarkovStateModel 28 | 29 | from pyemma.msm import MaximumLikelihoodMSM, ImpliedTimescales 30 | from pyemma.plots import plot_implied_timescales 31 | 32 | 33 | class TestItsPlot(unittest.TestCase): 34 | 35 | @classmethod 36 | def setUpClass(cls): 37 | P = np.array([[0.5, .25, .25, 0.], 38 | [0., .25, .5, .25], 39 | [.25, .25, .5, 0], 40 | [.25, .25, .25, .25], 41 | ]) 42 | # bogus its object 43 | lags = [1, 2, 3, 5, 10] 44 | cls.dtraj = MarkovStateModel(P).simulate(1000) 45 | cls.estimator = MaximumLikelihoodMSM(dt_traj='10 ps') 46 | cls.its = ImpliedTimescales(estimator=cls.estimator, n_jobs=1) 47 | cls.its.estimate(cls.dtraj, lags=lags) 48 | 49 | cls.refs = cls.its.timescales[-1] 50 | return cls 51 | 52 | def test_plot(self): 53 | plot_implied_timescales(self.its, 54 | refs=self.refs) 55 | 56 | def test_nits(self): 57 | plot_implied_timescales(self.its, 58 | refs=self.refs, nits=2) 59 | 60 | def test_process(self): 61 | plot_implied_timescales(self.its, refs=self.refs, process=[1, 2], dt=0.01, units='ns') 62 | 63 | def test_its_estimated_with_only_ts(self): 64 | its = ImpliedTimescales(estimator=self.estimator, lags=[1, 2, 3], only_timescales=True, n_jobs=1) 65 | its.estimate(self.dtraj) 66 | plot_implied_timescales(its) 67 | 68 | def test_its_estimated_with_only_ts_samples(self): 69 | from pyemma.msm import BayesianMSM 70 | its = ImpliedTimescales(estimator=BayesianMSM(nsamples=2), lags=[1, 2, 3], only_timescales=True, n_jobs=1) 71 | its.estimate(self.dtraj) 72 | plot_implied_timescales(its) 73 | 74 | 75 | if __name__ == "__main__": 76 | unittest.main() 77 | -------------------------------------------------------------------------------- /pyemma/plots/tests/test_markovtests.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2016, 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | ''' 20 | Created on 23.03.2016 21 | 22 | @author: marscher 23 | ''' 24 | 25 | import unittest 26 | import numpy as np 27 | from deeptime.markov.msm import MarkovStateModel 28 | 29 | import pyemma 30 | 31 | from pyemma.plots import plot_cktest 32 | 33 | class TestItsPlot(unittest.TestCase): 34 | 35 | @classmethod 36 | def setUpClass(cls): 37 | P = np.array([[0.5, .25, .25, 0.], 38 | [0., .25, .5, .25], 39 | [.25, .25, .5, 0], 40 | [.25, .25, .25, .25], 41 | ]) 42 | dtrajs = [MarkovStateModel(P).simulate(1000) for _ in range(5)] 43 | msm_obj = pyemma.msm.MaximumLikelihoodMSM() 44 | msm_obj.estimate(dtrajs) 45 | cls.ck = msm_obj.cktest(3, n_jobs=1) 46 | def test_plot(self): 47 | plot_cktest(self.ck) 48 | 49 | def test_plot_kwargs(self): 50 | plot_cktest(self.ck, marker='o', markerfacecolor='red', linewidth=2, label='testlabel') 51 | 52 | def test_plot_kwargs_no_def_overriding(self): 53 | plot_cktest(self.ck, marker='o', markerfacecolor='red', linewidth=2, label='testlabel', 54 | color='blue', linestyle='solid' 55 | ) 56 | 57 | -------------------------------------------------------------------------------- /pyemma/plots/tests/test_plots1d.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2018 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | 19 | import unittest 20 | import numpy as np 21 | 22 | from pyemma.plots.plots1d import plot_feature_histograms 23 | import matplotlib.pyplot as plt 24 | 25 | 26 | class TestPlots1d(unittest.TestCase): 27 | @classmethod 28 | def setUpClass(cls): 29 | cls.data = np.random.rand(500, 10) 30 | 31 | def test_feature_histograms(self): 32 | fig, _ = plot_feature_histograms(self.data) 33 | plt.close(fig) 34 | 35 | def test_invalid_input(self): 36 | with self.assertRaises(ValueError): 37 | fig, _ = plot_feature_histograms(self.data, feature_labels=np.random.rand(5)) 38 | plt.close(fig) 39 | 40 | def test_feature_histograms_mpl_arguments(self): 41 | labels = ['PyEMMA' for _ in range(self.data.shape[1])] 42 | fig, _ = plot_feature_histograms(self.data, 43 | feature_labels=labels, 44 | ylog=True, 45 | n_bins=10, 46 | color='g') 47 | plt.close(fig) 48 | 49 | def test_feature_histograms_ax_argument(self): 50 | from matplotlib.pyplot import subplots 51 | fig, ax = subplots() 52 | fig, _ = plot_feature_histograms(self.data, ax=ax) 53 | plt.close(fig) 54 | -------------------------------------------------------------------------------- /pyemma/pyemma.cfg: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # PyEMMA configuration file 3 | # 4 | # notes: 5 | # - comments are not allowed in line, since they would be appended to the value! 6 | ################################################################################ 7 | 8 | [pyemma] 9 | # configuration notice shown? 10 | show_config_notification = False 11 | 12 | # Source to logging configuration file (YAML). 13 | # Special value: DEFAULT (use default config). 14 | # If this is set to a filename, it will be red to configure logging. If it is a 15 | # relative path, it is assumed to be located next to where you start your interpreter. 16 | logging_config = DEFAULT 17 | 18 | # show or hide progress bars globally? 19 | show_progress_bars = True 20 | 21 | # useful for trajectory formats, for which one has to read the whole file to get len 22 | # eg. XTC format. 23 | use_trajectory_lengths_cache = True 24 | # maximum entries in database 25 | traj_info_max_entries = 50000 26 | # max size in MB 27 | traj_info_max_size = 500 28 | 29 | # check output of iterators in pyemma.coordinates for infinity and NaN, useful for debug purposes. 30 | coordinates_check_output = False 31 | 32 | # latest version check 33 | check_version = True 34 | 35 | # mute progressbars and logging events (only critical) 36 | mute = False 37 | 38 | # default chunksize to use for coordinate transformations, only intergers with suffix [k,m,g] 39 | # if you have a lot of memory available, you can try to increase this. 40 | default_chunksize = 256m 41 | -------------------------------------------------------------------------------- /pyemma/thermo/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2015, 2016 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | r""" 19 | .. currentmodule:: pyemma.thermo 20 | 21 | User-Functions 22 | ============== 23 | For most users, the following high-level functions are sufficient to 24 | estimate models from data. 25 | 26 | .. autosummary:: 27 | :toctree: generated/thermo-api 28 | 29 | estimate_umbrella_sampling 30 | estimate_multi_temperature 31 | tram 32 | dtram 33 | wham 34 | mbar 35 | 36 | Thermo classes 37 | ============== 38 | **Estimators** to generate models from data. If you are not an expert user, 39 | use the API functions above. 40 | 41 | .. autosummary:: 42 | :toctree: generated/thermo-estimators 43 | 44 | StationaryModel 45 | MultiThermModel 46 | MEMM 47 | WHAM 48 | MBAR 49 | DTRAM 50 | TRAM 51 | 52 | """ 53 | 54 | from pyemma.thermo.models import StationaryModel, MultiThermModel, MEMM 55 | from pyemma.thermo.estimators import WHAM, MBAR, DTRAM, TRAM, EmptyState 56 | 57 | # high-level api 58 | from .api import * 59 | -------------------------------------------------------------------------------- /pyemma/thermo/estimators/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2015, 2016 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | from .WHAM_estimator import WHAM 19 | from .MBAR_estimator import MBAR 20 | from .DTRAM_estimator import DTRAM 21 | from .TRAM_estimator import TRAM, EmptyState 22 | -------------------------------------------------------------------------------- /pyemma/thermo/estimators/_base.py: -------------------------------------------------------------------------------- 1 | 2 | class Undefined(object): pass 3 | 4 | 5 | class ThermoBase(object): 6 | 7 | __serialize_version = 0 8 | __serialize_fields = ('umbrella_centers', 'force_constants', 'temperatures', 'dt_traj') 9 | 10 | @property 11 | def umbrella_centers(self): 12 | """ The individual umbrella centers labelled accordingly to ttrajs. 13 | (only set, when estimated from umbrella data). 14 | """ 15 | try: 16 | return self._umbrella_centers 17 | except AttributeError: 18 | return Undefined 19 | 20 | @umbrella_centers.setter 21 | def umbrella_centers(self, value): 22 | self._umbrella_centers = value 23 | 24 | @property 25 | def force_constants(self): 26 | """The individual force matrices labelled accordingly to ttrajs. 27 | (only set, when estimated from umbrella data). 28 | """ 29 | try: 30 | return self._force_constants 31 | except AttributeError: 32 | return Undefined 33 | 34 | @force_constants.setter 35 | def force_constants(self, value): 36 | self._force_constants = value 37 | 38 | @property 39 | def temperatures(self): 40 | """ The individual temperatures labelled accordingly to ttrajs. 41 | (only set, when estimated from multi-temperature data). 42 | """ 43 | try: 44 | return self._temperatures 45 | except AttributeError: 46 | return Undefined 47 | 48 | @temperatures.setter 49 | def temperatures(self, value): 50 | self._temperatures = value 51 | 52 | @property 53 | def dt_traj(self): 54 | return self._dt_traj 55 | 56 | @dt_traj.setter 57 | def dt_traj(self, value): 58 | # time step 59 | self._dt_traj = value 60 | from pyemma.util.units import TimeUnit 61 | self.timestep_traj = TimeUnit(self.dt_traj) 62 | -------------------------------------------------------------------------------- /pyemma/thermo/estimators/_callback.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2016 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | import time 19 | 20 | 21 | class _ProgressIndicatorCallBack(object): 22 | def __init__(self): 23 | self.time = 0.0 24 | 25 | # TODO: unify this concept in ProgressReporter (but make it adaptive) 26 | def waiting(self): 27 | now = time.time() 28 | if now - self.time < .2: 29 | return True 30 | else: 31 | self.time = now 32 | return False 33 | 34 | 35 | class _IterationProgressIndicatorCallBack(_ProgressIndicatorCallBack): 36 | def __init__(self, reporter, description, stage): 37 | super(_IterationProgressIndicatorCallBack, self).__init__() 38 | reporter._progress_register(10, description, stage=stage, tqdm_args=dict(smoothing=0.5)) 39 | self.stage = stage 40 | self.reporter = reporter 41 | 42 | def __call__(self, *args, **kwargs): 43 | if not self.reporter.show_progress: return 44 | if self.waiting(): return 45 | self.reporter._prog_rep_progressbars[self.stage].total = kwargs['maxiter'] 46 | self.reporter._progress_update(1, stage=self.stage) 47 | 48 | 49 | class _ConvergenceProgressIndicatorCallBack(_ProgressIndicatorCallBack): 50 | def __init__(self, reporter, stage, maxiter, maxerr, subcallback=None): 51 | self.template = str(stage) + ' increment={err:0.1e}/{maxerr:0.1e}' 52 | description = str(stage) 53 | super(_ConvergenceProgressIndicatorCallBack, self).__init__() 54 | self.final = maxiter 55 | reporter._progress_register(int(self.final), description, stage=stage, tqdm_args=dict(smoothing=0.5)) 56 | self.stage = stage 57 | self.reporter = reporter 58 | self.state = 0.0 59 | self.subcallback = subcallback 60 | 61 | def __call__(self, *args, **kwargs): 62 | if self.subcallback is not None: 63 | self.subcallback(*args, **kwargs) 64 | if not self.reporter.show_progress: return 65 | if self.waiting(): return 66 | current = kwargs['iteration_step'] 67 | if 'err' in kwargs and 'maxerr' in kwargs: 68 | err_str = self.template.format(err=kwargs['err'], maxerr=kwargs['maxerr']) 69 | self.reporter._progress_set_description(self.stage, err_str) 70 | if current > 0.0 and self.state < current <= self.final: 71 | difference = current - self.state 72 | self.reporter._progress_update(difference, stage=self.stage) 73 | self.state = current 74 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/.gitignore: -------------------------------------------------------------------------------- 1 | # auto-generated c files from Cython 2 | 3 | wham/wham.c 4 | mbar/mbar.c 5 | mbar_direct/mbar_direct.c 6 | tram/tram.c 7 | tram_direct/tram_direct.c 8 | dtram/dtram.c 9 | bar/bar.c 10 | util/util.c 11 | trammbar/trammbar.c 12 | trammbar_direct/trammbar_direct.c 13 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/thermo/extensions/__init__.py -------------------------------------------------------------------------------- /pyemma/thermo/extensions/bar/_bar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of thermotools. 3 | * 4 | * Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | * 6 | * thermotools is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "../util/_util.h" 21 | 22 | extern double _bar_df(double *db_IJ, int L1, double *db_JI, int L2, double *scratch) 23 | { 24 | int i; 25 | double ln_avg1; 26 | double ln_avg2; 27 | for (i=0; i0 ? 0 : db_IJ[i]; 30 | } 31 | ln_avg1 = _logsumexp_sort_kahan_inplace(scratch, L1); 32 | for (i=0; i0 ? 0 : db_JI[i]; 35 | } 36 | ln_avg2 = _logsumexp_sort_kahan_inplace(scratch, L2); 37 | return ln_avg2 - ln_avg1; 38 | } -------------------------------------------------------------------------------- /pyemma/thermo/extensions/bar/_bar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of thermotools. 3 | * 4 | * Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | * 6 | * thermotools is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef THERMOTOOLS_BAR 21 | #define THERMOTOOLS_BAR 22 | 23 | double _bar_df(double *db_IJ, int L1, double *db_JI, int L2, double *scratch); 24 | 25 | #endif 26 | 27 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/bar/bar.pyx: -------------------------------------------------------------------------------- 1 | # This file is part of thermotools. 2 | # 3 | # Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # thermotools is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | r""" 19 | Python interface to the BAR ratio initialisation. 20 | """ 21 | 22 | import numpy as _np 23 | cimport numpy as _np 24 | 25 | __all__ = ['df'] 26 | 27 | cdef extern from "_bar.h": 28 | double _bar_df(double *db_IJ, int L1, double *db_JI, int L2, double *scratch) 29 | 30 | def df(_np.ndarray[double, ndim=1, mode="c"] db_IJ not None, 31 | _np.ndarray[double, ndim=1, mode="c"] db_JI not None, 32 | _np.ndarray[double, ndim=1, mode="c"] scratch not None): 33 | 34 | """ Free energy differences between two thermodynamic states using Bennett's 35 | acceptance ratio (BAR). 36 | Estimates the free energy difference between two thermodynamic states 37 | using Bennett's acceptance ratio (BAR) [1]_. As an input, we need 38 | a set of reduced bias energy differences. Reduced bias energy differences 39 | are given in units of the thermal energy, often denoted by 40 | :math:`\Delta b^{IJ}(x) = (B^I(x \in J) - B(x \in I)) / kT^I` 41 | where B(x) is the bias energy function and kT is the thermal 42 | energy. 43 | 44 | Parameters 45 | ---------- 46 | db_IJ : numpy.ndarray(shape=(L1,), dtype=numpy.float64) 47 | Reduced biased energy differences for samples generated in thermodynamic state I. 48 | db_JI : numpy.ndarray(shape=(L2,), dtype=numpy.float64) 49 | Reduced biased energy differences for samples generated in thermodynamic state J. 50 | sctatch : numpy.ndarray(shape=(max(L1, L2)), dtype=numpy.float64) 51 | Empty scatch array for internal data processing 52 | 53 | Returns 54 | ------- 55 | df : float 56 | free energy difference between states I and J defined by :math:`f^IJ = f^J-f^I`. 57 | 58 | References 59 | ---------- 60 | .. [1] Bennett, C. H.: Efficient Estimation of Free Energy Differences from 61 | Monte Carlo Data. J. Comput. Phys. 22, 245-268 (1976) 62 | """ 63 | return _bar_df( 64 | _np.PyArray_DATA(db_IJ), 65 | db_IJ.shape[0], 66 | _np.PyArray_DATA(db_JI), 67 | db_JI.shape[0], 68 | _np.PyArray_DATA(scratch)) 69 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/callback.py: -------------------------------------------------------------------------------- 1 | # This file is part of thermotools. 2 | # 3 | # Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # thermotools is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | r""" 19 | This module provides a custom exception to interrupt estimation runs via callback functions. 20 | """ 21 | 22 | __all__ = [ 23 | 'CallbackInterrupt', 24 | 'generic_callback_stop'] 25 | 26 | class CallbackInterrupt(Exception): 27 | r""" 28 | Exception class estimation interruptions via callback functions. 29 | """ 30 | def __init__(self, msg): 31 | self.msg = msg 32 | def __str__(self): 33 | return "[CALLBACKINTERRUPT] %s" % self.msg 34 | 35 | def generic_callback_stop(**kwargs): 36 | r""" 37 | This is a generic callback serving as example and for testing purposes: it just stops 38 | the estimation at first evaluation of the callback function. 39 | """ 40 | raise CallbackInterrupt("STOP") 41 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/dtram/_dtram.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of thermotools. 3 | * 4 | * Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | * 6 | * thermotools is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef THERMOTOOLS_DTRAM 21 | #define THERMOTOOLS_DTRAM 22 | 23 | #define THERMOTOOLS_DTRAM_PRIOR 1.0E-10 24 | #define THERMOTOOLS_DTRAM_LOG_PRIOR -23.025850929940457 25 | 26 | void _dtram_init_log_lagrangian_mult( 27 | int *count_matrices, int n_therm_states, int n_conf_states, double *log_lagrangian_mult); 28 | 29 | void _dtram_update_log_lagrangian_mult( 30 | double *log_lagrangian_mult, double *bias_energies, double *conf_energies, int *count_matrices, 31 | int n_therm_states, int n_conf_states, double *scratch_M, double *new_log_lagrangian_mult); 32 | 33 | void _dtram_update_conf_energies( 34 | double *log_lagrangian_mult, double *bias_energies, double *conf_energies, int *count_matrices, int n_therm_states, 35 | int n_conf_states, double *scratch_TM, double *new_conf_energies); 36 | 37 | void _dtram_estimate_transition_matrix( 38 | double *log_lagrangian_mult, double *bias_energies, double *conf_energies, int *count_matrix, 39 | int n_conf_states, double *scratch_M, double *transition_matrix); 40 | 41 | void _dtram_get_therm_energies( 42 | double *bias_energies, double *conf_energies, int n_therm_states, int n_conf_states, 43 | double *scratch_M, double *therm_energies); 44 | 45 | void _dtram_normalize( 46 | int n_therm_states, int n_conf_states, double *scratch_M, double *therm_energies, double *conf_energies); 47 | 48 | double _dtram_get_loglikelihood( 49 | int *count_matrices, double *transition_matrices, 50 | int n_therm_states, int n_conf_states); 51 | 52 | double _dtram_get_prior(void); 53 | double _dtram_get_log_prior(void); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/mbar/_mbar.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of thermotools. 3 | * 4 | * Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | * 6 | * thermotools is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef THERMOTOOLS_MBAR 21 | #define THERMOTOOLS_MBAR 22 | 23 | void _mbar_update_therm_energies( 24 | double *log_therm_state_counts, double *therm_energies, double *bias_energy_sequence, 25 | int n_therm_states, int seq_length, double *scratch_T, double *new_therm_energies); 26 | 27 | void _mbar_get_conf_energies( 28 | double *log_therm_state_counts, double *therm_energies, 29 | double *bias_energy_sequence, int * conf_state_sequence, 30 | int n_therm_states, int n_conf_states, int seq_length, 31 | double *scratch_T, double *conf_energies, double *biased_conf_energies); 32 | 33 | void _mbar_normalize( 34 | int n_therm_states, int n_conf_states, double *scratch_M, 35 | double *therm_energies, double *conf_energies, double *biased_conf_energies); 36 | 37 | void _mbar_get_pointwise_unbiased_free_energies( 38 | int k, double *log_therm_state_counts, double *therm_energies, 39 | double *bias_energy_sequence, 40 | int n_therm_states, int seq_length, 41 | double *scratch_T, double *pointwise_unbiased_free_energies); 42 | 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/mbar_direct/_mbar_direct.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of thermotools. 3 | * 4 | * Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | * 6 | * thermotools is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include "../util/_util.h" 22 | #include "_mbar_direct.h" 23 | 24 | void _mbar_direct_update_therm_weights( 25 | int *therm_state_counts, double *therm_weights, double *bias_weight_sequence, 26 | int n_therm_states, int seq_length, double *new_therm_weights) 27 | { 28 | int K, x, L; 29 | double divisor; 30 | /* assume that new_therm_weights was set to zero by the caller on the first call */ 31 | for(x=0; x. 18 | */ 19 | 20 | #ifndef THERMOTOOLS_MBAR 21 | #define THERMOTOOLS_MBAR 22 | 23 | void _mbar_direct_update_therm_weights( 24 | int *therm_state_counts, double *therm_weights, double *bias_weight_sequence, 25 | int n_therm_states, int seq_length, double *new_therm_weights); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/tram_direct/_tram_direct.h: -------------------------------------------------------------------------------- 1 | #ifndef THERMOTOOLS_TRAM_DIRECT_H 2 | #define THERMOTOOLS_TRAM_DIRECT_H 3 | 4 | void _tram_direct_update_lagrangian_mult( 5 | double *lagrangian_mult, double *biased_conf_weights, int *count_matrices, int* state_counts, 6 | int n_therm_states, int n_conf_states, double *new_lagrangian_mult); 7 | 8 | void _tram_direct_get_Ref_K_i( 9 | double *lagrangian_mult, double *biased_conf_weights, int *count_matrices, 10 | int *state_counts, int n_therm_states, int n_conf_states, double *R_K_i 11 | #ifdef TRAMMBAR 12 | , 13 | double *therm_weights, int *equilibrium_therm_state_counts, 14 | double overcounting_factor 15 | #endif 16 | ); 17 | 18 | void _tram_direct_update_biased_conf_weights( 19 | double *bias_sequence, int *state_sequence, int seq_length, double *R_K_i, 20 | int n_therm_states, int n_conf_states, double *new_biased_conf_weights); 21 | 22 | void _tram_direct_dtram_like_update( 23 | double *lagrangian_mult, double *biased_conf_weights, int *count_matrices, int *state_counts, 24 | int n_therm_states, int n_conf_states, double *scratch_M, int *scratch_M_int, double *new_biased_conf_weights); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/wham/_wham.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of thermotools. 3 | * 4 | * Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | * 6 | * thermotools is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "../util/_util.h" 21 | 22 | extern void _wham_update_conf_energies( 23 | double *log_therm_state_counts, double *log_conf_state_counts, 24 | double *therm_energies, double *bias_energies, 25 | int n_therm_states, int n_conf_states, double *scratch_T, double *conf_energies) 26 | { 27 | int i, K; 28 | for(i=0; i 0) 77 | scratch_S[o++] = therm_state_counts[i] * therm_energies[i]; 78 | } 79 | for(i=0; i 0) 82 | scratch_S[o++] = -conf_state_counts[i] * conf_energies[i]; 83 | } 84 | _mixed_sort(scratch_S, 0, o - 1); 85 | return _kahan_summation(scratch_S, o); 86 | } 87 | -------------------------------------------------------------------------------- /pyemma/thermo/extensions/wham/_wham.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of thermotools. 3 | * 4 | * Copyright 2015 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | * 6 | * thermotools is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef THERMOTOOLS_WHAM 21 | #define THERMOTOOLS_WHAM 22 | 23 | void _wham_update_conf_energies( 24 | double *log_therm_state_counts, double *log_conf_state_counts, 25 | double *therm_energies, double *bias_energies, 26 | int n_therm_states, int n_conf_states, double *scratch_T, double *conf_energies); 27 | 28 | void _wham_update_therm_energies( 29 | double *conf_energies, double *bias_energies, int n_therm_states, int n_conf_states, 30 | double *scratch_M, double *therm_energies); 31 | 32 | void _wham_normalize( 33 | int n_therm_states, int n_conf_states, 34 | double *scratch_M, double *therm_energies, double *conf_energies); 35 | 36 | double _wham_get_loglikelihood( 37 | int *therm_state_counts, int *conf_state_counts, 38 | double *therm_energies, double *conf_energies, 39 | int n_therm_states, int n_conf_states, double *scratch_S); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /pyemma/thermo/models/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2015, 2016 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | from .stationary import StationaryModel 19 | from .multi_therm import MultiThermModel 20 | from .memm import MEMM 21 | -------------------------------------------------------------------------------- /pyemma/thermo/tests/test_DTRAM.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2020 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | import unittest 19 | 20 | import numpy as np 21 | import pyemma.thermo 22 | 23 | 24 | class TestDTRAMConnectedSet(unittest.TestCase): 25 | def test_DTRAM_connected_set(self): 26 | dtrajs = [np.array([3, 0, 1, 0, 1]), np.array([3, 1, 2, 1, 2])] 27 | ttrajs = [np.array([0, 0, 0, 0, 0]), np.array([1, 1, 1, 1, 1])] 28 | dtram = pyemma.thermo.DTRAM(bias_energies_full=np.zeros((2, 4)), lag=1) 29 | dtram.estimate((ttrajs, dtrajs)) 30 | np.testing.assert_allclose(dtram.active_set, [0, 1, 2]) 31 | np.testing.assert_allclose(dtram.models[0].active_set, [0, 1]) 32 | np.testing.assert_allclose(dtram.models[1].active_set, [1, 2]) 33 | np.testing.assert_allclose(dtram.stationary_distribution, np.ones(3)/3) 34 | np.testing.assert_allclose(dtram.stationary_distribution_full_state, np.array([1., 1., 1., 0.])/3) 35 | np.testing.assert_allclose(dtram.models[0].stationary_distribution, np.array([0.5, 0.5])) 36 | np.testing.assert_allclose(dtram.models[0].stationary_distribution_full_state, np.array([0.5, 0.5, 0., 0.])) 37 | np.testing.assert_allclose(dtram.models[1].stationary_distribution, np.array([0.5, 0.5])) 38 | np.testing.assert_allclose(dtram.models[1].stationary_distribution_full_state, np.array([0., 0.5, 0.5, 0.])) 39 | 40 | 41 | if __name__ == "__main__": 42 | unittest.main() 43 | -------------------------------------------------------------------------------- /pyemma/thermo/util/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2016 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | 18 | from .util import * 19 | -------------------------------------------------------------------------------- /pyemma/util/.gitignore: -------------------------------------------------------------------------------- 1 | omp_threads.c 2 | -------------------------------------------------------------------------------- /pyemma/util/__init__.py: -------------------------------------------------------------------------------- 1 | from ._config import Config as _Config 2 | 3 | # default config instance 4 | config = _Config() 5 | -------------------------------------------------------------------------------- /pyemma/util/debug.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | ''' This module registers some debug handlers upon the call of 20 | :py:func:register_signal_handlers 21 | 22 | 1. Show a stack trace of the current frame 23 | 2. Attach the Python debugger PDB to the current process 24 | 25 | Created on 15.10.2015 26 | 27 | @author: marscher 28 | ''' 29 | 30 | import signal 31 | from logging import getLogger 32 | 33 | _logger = None 34 | 35 | SIGNAL_STACKTRACE = 23 36 | SIGNAL_PDB = 43 37 | 38 | 39 | def _show_stacktrace(sig, frame): 40 | import traceback 41 | from io import StringIO 42 | 43 | global _logger 44 | if _logger is None: 45 | _logger = getLogger('pyemma.dbg') 46 | 47 | out = StringIO() 48 | 49 | traceback.print_stack(frame, file=out) 50 | 51 | out.seek(0) 52 | trace = out.read() 53 | _logger.info(trace) 54 | 55 | def _handle_pdb(sig, frame): 56 | import pdb 57 | pdb.Pdb().set_trace(frame) 58 | 59 | 60 | def register_signal_handlers(): 61 | r""" Registeres some debug helping functions at the current Python process. 62 | 63 | Namely a stack trace generator (which uses the logging system) and a debugger 64 | attaching function. 65 | To trigger them, send the corresponding signal to the process:: 66 | 67 | 1. kill -42 $PID # obtain a stack trace 68 | 2. kill -43 $PID # attach the debugger to the current stack frame 69 | 70 | For the first signal, a stack trace originating from the current frame will 71 | be logged using PyEMMAs logging system. 72 | 73 | The second signal stops your program at the current stack frame by using 74 | Pythons internal debugger PDB. 75 | See https://docs.python.org/2/library/pdb.html for information on how to use 76 | the debugger. 77 | 78 | To obtain a stack trace, just send the signal 42 to the current Python process id. 79 | This id can be obtained via: 80 | 81 | >>> import os # doctest: +SKIP 82 | >>> os.getpid() # doctest: +SKIP 83 | 34588 84 | 85 | To send the signal you can use kill on Linux and OSX:: 86 | 87 | kill -42 34588 88 | """ 89 | signal.signal(SIGNAL_STACKTRACE, _show_stacktrace) 90 | signal.signal(SIGNAL_PDB, _handle_pdb) 91 | 92 | 93 | def unregister_signal_handlers(): 94 | """ set signal handlers to default """ 95 | signal.signal(SIGNAL_STACKTRACE, signal.SIG_IGN) 96 | signal.signal(SIGNAL_PDB, signal.SIG_IGN) 97 | -------------------------------------------------------------------------------- /pyemma/util/exceptions.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | ''' 20 | Created on May 26, 2014 21 | 22 | @author: marscher 23 | ''' 24 | 25 | 26 | class SpectralWarning(RuntimeWarning): 27 | pass 28 | 29 | 30 | class ImaginaryEigenValueWarning(SpectralWarning): 31 | pass 32 | 33 | 34 | class PrecisionWarning(RuntimeWarning): 35 | r""" 36 | This warning indicates that some operation in your code leads 37 | to a conversion of datatypes, which involves a loss/gain in 38 | precision. 39 | 40 | """ 41 | pass 42 | 43 | 44 | class NotConvergedWarning(RuntimeWarning): 45 | r""" 46 | This warning indicates that some iterative procdure has not 47 | converged or reached the maximum number of iterations implemented 48 | as a safe guard to prevent arbitrary many iterations in loops with 49 | a conditional termination criterion. 50 | 51 | """ 52 | pass 53 | 54 | 55 | class EfficiencyWarning(UserWarning): 56 | r"""Some operation or input data leads to a lack of efficiency""" 57 | pass 58 | 59 | 60 | class ParserWarning(UserWarning): 61 | """ Some user defined variable could not be parsed and is ignored/replaced. """ 62 | pass 63 | 64 | 65 | class ConfigDirectoryException(Exception): 66 | """ Some operation with PyEMMAs configuration directory went wrong. """ 67 | pass 68 | 69 | 70 | class PyEMMA_DeprecationWarning(UserWarning): 71 | """You are using a feature, which will be removed in a future release. You have been warned!""" 72 | pass 73 | 74 | 75 | class PyEMMA_UserWarning(UserWarning): 76 | """ general user warning.""" 77 | pass 78 | -------------------------------------------------------------------------------- /pyemma/util/files.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | ''' 21 | Created on 17.02.2014 22 | 23 | @author: marscher 24 | ''' 25 | 26 | import os 27 | import errno 28 | import tempfile 29 | import shutil 30 | 31 | 32 | def mkdir_p(path): 33 | try: 34 | os.makedirs(path) 35 | except OSError as exc: # Python >2.5 36 | if exc.errno == errno.EEXIST and os.path.isdir(path): 37 | pass 38 | else: 39 | raise 40 | 41 | 42 | class TemporaryDirectory(object): 43 | """Create and return a temporary directory. This has the same 44 | behavior as mkdtemp but can be used as a context manager. For 45 | example: 46 | 47 | Examples 48 | -------- 49 | >>> import os 50 | >>> with TemporaryDirectory() as tmp: 51 | ... path = os.path.join(tmp, "myfile.dat") 52 | ... fh = open(path, 'w') 53 | ... _ = fh.write('hello world') 54 | ... fh.close() 55 | 56 | Upon exiting the context, the directory and everything contained 57 | in it are removed. 58 | """ 59 | 60 | def __init__(self, prefix='', suffix='', dir=None): 61 | self.prefix = prefix 62 | self.suffix = suffix 63 | self.dir = dir 64 | self.tmpdir = None 65 | 66 | def __enter__(self): 67 | self.tmpdir = tempfile.mkdtemp(suffix=self.suffix, prefix=self.prefix, 68 | dir=self.dir) 69 | return self.tmpdir 70 | 71 | def __exit__(self, *args): 72 | shutil.rmtree(self.tmpdir, ignore_errors=True) 73 | -------------------------------------------------------------------------------- /pyemma/util/indices.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | import numpy as np 20 | 21 | 22 | def combinations(seq, k): 23 | """ Return j length subsequences of elements from the input iterable. 24 | 25 | This version uses Numpy/Scipy and should be preferred over itertools. It avoids 26 | the creation of all intermediate Python objects. 27 | 28 | Examples 29 | -------- 30 | 31 | >>> import numpy as np 32 | >>> from itertools import combinations as iter_comb 33 | >>> x = np.arange(3) 34 | >>> c1 = combinations(x, 2) 35 | >>> print(c1) 36 | [[0 1] 37 | [0 2] 38 | [1 2]] 39 | >>> c2 = np.array(tuple(iter_comb(x, 2))) 40 | >>> print(c2) 41 | [[0 1] 42 | [0 2] 43 | [1 2]] 44 | """ 45 | from itertools import combinations as _combinations, chain 46 | from scipy.special import comb 47 | 48 | count = comb(len(seq), k, exact=True) 49 | res = np.fromiter(chain.from_iterable(_combinations(seq, k)), 50 | int, count=count*k) 51 | return res.reshape(-1, k) 52 | 53 | 54 | def product(*arrays): 55 | """ Generate a cartesian product of input arrays. 56 | 57 | Parameters 58 | ---------- 59 | arrays : list of array-like 60 | 1-D arrays to form the cartesian product of. 61 | 62 | Returns 63 | ------- 64 | out : ndarray 65 | 2-D array of shape (M, len(arrays)) containing cartesian products 66 | formed of input arrays. 67 | 68 | """ 69 | arrays = [np.asarray(x) for x in arrays] 70 | shape = (len(x) for x in arrays) 71 | dtype = arrays[0].dtype 72 | 73 | ix = np.indices(shape) 74 | ix = ix.reshape(len(arrays), -1).T 75 | 76 | out = np.empty_like(ix, dtype=dtype) 77 | 78 | for n, _ in enumerate(arrays): 79 | out[:, n] = arrays[n][ix[:, n]] 80 | 81 | return out 82 | -------------------------------------------------------------------------------- /pyemma/util/numeric.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | ''' 20 | Created on 28.10.2013 21 | 22 | @author: marscher 23 | ''' 24 | from numpy.testing import assert_allclose as assert_allclose_np 25 | 26 | __all__ = ['assert_allclose', 27 | ] 28 | 29 | 30 | def assert_allclose(actual, desired, rtol=1.e-5, atol=1.e-8, 31 | err_msg='', verbose=True): 32 | r"""wrapper for numpy.testing.allclose with default tolerances of 33 | numpy.allclose. Needed since testing method has different values.""" 34 | return assert_allclose_np(actual, desired, rtol=rtol, atol=atol, 35 | err_msg=err_msg, verbose=verbose) 36 | 37 | 38 | def _hash_numpy_array(x): 39 | import numpy as np 40 | import hashlib 41 | from io import BytesIO 42 | from scipy.sparse import issparse 43 | v = hashlib.sha1() 44 | v.update(x.data) 45 | if issparse(x): 46 | v.update(x.indices) 47 | else: 48 | v.update(str(x.shape).encode('ascii')) 49 | v.update(str(x.strides).encode('ascii'))# if x.strides is not None else '')) 50 | #v.update(str(x.strides).encode('ascii')) 51 | return hash(v.digest()) 52 | -------------------------------------------------------------------------------- /pyemma/util/testing_tools.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | 4 | class MockLoggingHandler(logging.Handler): 5 | """Mock logging handler to check for expected logs.""" 6 | 7 | def __init__(self, *args, **kwargs): 8 | self.reset() 9 | logging.Handler.__init__(self, *args, **kwargs) 10 | 11 | def emit(self, record): 12 | self.messages[record.levelname.lower()].append(record.getMessage()) 13 | 14 | def reset(self): 15 | self.messages = { 16 | 'debug': [], 17 | 'info': [], 18 | 'warning': [], 19 | 'error': [], 20 | 'critical': [], 21 | } 22 | -------------------------------------------------------------------------------- /pyemma/util/tests/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | __author__ = 'noe' 21 | -------------------------------------------------------------------------------- /pyemma/util/tests/data/dtraj.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markovmodel/PyEMMA/3327f28b49e388e1ce4a6a83ab2f0c0ac7ca5050/pyemma/util/tests/data/dtraj.npy -------------------------------------------------------------------------------- /pyemma/util/tests/statistics_test.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | ''' 21 | Created on Jul 25, 2014 22 | 23 | @author: noe 24 | ''' 25 | 26 | import unittest 27 | from pyemma.util import statistics 28 | import numpy as np 29 | 30 | 31 | 32 | class TestStatistics(unittest.TestCase): 33 | 34 | def assertConfidence(self, sample, alpha, precision): 35 | alpha = 0.5 36 | conf = statistics.confidence_interval(sample, alpha) 37 | 38 | n_in = 0.0 39 | for i in range(len(sample)): 40 | if sample[i] > conf[0] and sample[i] < conf[1]: 41 | n_in += 1.0 42 | 43 | assert(alpha - (n_in/len(sample)) < precision) 44 | 45 | def test_confidence_interval(self): 46 | # exponential distribution 47 | self.assertConfidence(np.random.exponential(size=10000), 0.5, 0.01) 48 | self.assertConfidence(np.random.exponential(size=10000), 0.8, 0.01) 49 | self.assertConfidence(np.random.exponential(size=10000), 0.95, 0.01) 50 | # Gaussian distribution 51 | self.assertConfidence(np.random.normal(size=10000), 0.5, 0.01) 52 | self.assertConfidence(np.random.normal(size=10000), 0.8, 0.01) 53 | self.assertConfidence(np.random.normal(size=10000), 0.95, 0.01) 54 | 55 | if __name__ == "__main__": 56 | unittest.main() 57 | -------------------------------------------------------------------------------- /pyemma/util/tests/test_log.py: -------------------------------------------------------------------------------- 1 | # This file is part of PyEMMA. 2 | # 3 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 4 | # 5 | # PyEMMA is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | ''' 18 | Created on 09.03.2016 19 | 20 | @author: marscher 21 | ''' 22 | from tempfile import NamedTemporaryFile 23 | import sys 24 | import unittest 25 | import logging 26 | 27 | 28 | from pyemma.util import log 29 | from pyemma.util import config 30 | from unittest import mock 31 | 32 | 33 | class TestNonWriteableLogFile(unittest.TestCase): 34 | 35 | def tearDown(self): 36 | # reset logging 37 | log.setup_logging(config) 38 | 39 | @unittest.skipIf('win32' in sys.platform, "disabled on win") 40 | def test(self): 41 | conf = b""" 42 | # do not disable other loggers by default. 43 | disable_existing_loggers: False 44 | 45 | # please do not change version, it is an internal variable used by Python. 46 | version: 1 47 | 48 | handlers: 49 | rotating_files: 50 | class: logging.handlers.RotatingFileHandler 51 | filename: /pyemma.log 52 | 53 | loggers: 54 | pyemma: 55 | level: INFO 56 | handlers: [rotating_files] 57 | """ 58 | with NamedTemporaryFile(delete=False) as f: 59 | f.write(conf) 60 | f.close() 61 | with mock.patch('pyemma.util.log.open', create=True) as mock_open: 62 | mock_open.return_value = open(f.name) 63 | 64 | log.setup_logging(config) 65 | assert logging.getLogger('pyemma').handlers[0].baseFilename.startswith(config.cfg_dir) 66 | 67 | @unittest.skip("not yet functional") 68 | def test_set_new_log_conf(self): 69 | import logging, copy, tempfile 70 | old_handlers = copy.copy(logging.getLogger('pyemma').handlers) 71 | log_file = tempfile.mktemp() 72 | file_handler = {'my_filehandler': {'class': 'logging.FileHandler', 'filename': log_file}, } 73 | new_conf = {'handlers': file_handler} 74 | 75 | from pyemma import config 76 | config.logging_config = new_conf 77 | 78 | logger = logging.getLogger('pyemma') 79 | log_str = "test-test-test-test-" + self.test_set_new_log_conf.__name__ 80 | logger.info(log_str) 81 | for h in logger.handlers: 82 | h.flush() 83 | 84 | with open(log_file) as fh: 85 | out = fh.read() 86 | 87 | self.assertIn(log_str, out) 88 | 89 | if __name__ == "__main__": 90 | unittest.main() 91 | -------------------------------------------------------------------------------- /pyemma/util/tests/test_shortcut.py: -------------------------------------------------------------------------------- 1 | 2 | # This file is part of PyEMMA. 3 | # 4 | # Copyright (c) 2015, 2014 Computational Molecular Biology Group, Freie Universitaet Berlin (GER) 5 | # 6 | # PyEMMA is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | 21 | from pyemma.util.annotators import shortcut, aliased, alias 22 | import unittest 23 | 24 | @shortcut("bar", "bar2") 25 | def foo(): 26 | """ sample docstring""" 27 | return True 28 | 29 | @aliased 30 | class Foo(object): 31 | @alias("bar2", "bar3") 32 | def bar(self): 33 | """ doc """ 34 | pass 35 | 36 | class TestShortcut_and_Aliases(unittest.TestCase): 37 | 38 | def test_shortcut(self): 39 | self.assertEqual(bar.__doc__, foo.__doc__) 40 | result = bar() 41 | self.assertTrue(result) 42 | 43 | self.assertEqual(bar2.__doc__, foo.__doc__) 44 | result = bar2() 45 | self.assertTrue(result) 46 | 47 | def test_alias_class(self): 48 | assert hasattr(Foo, "bar3") 49 | assert hasattr(Foo, "bar3") 50 | 51 | def test_alias_class_inst(self): 52 | inst = Foo() 53 | assert hasattr(inst, "bar2") 54 | assert hasattr(inst, "bar3") 55 | self.assertEqual(inst.bar.__doc__, inst.bar2.__doc__) 56 | -------------------------------------------------------------------------------- /pyemma/util/tests/test_units.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from pyemma.util.units import bytes_to_string 3 | 4 | class TestUnits(unittest.TestCase): 5 | 6 | def test_human_readable_byte_size(self): 7 | n_bytes = 1393500160 # about 1.394 GB 8 | self.assertEqual(bytes_to_string(n_bytes), "1.3GB", "this number of bytes should " 9 | "result in 1.3GB and not in %s" % bytes_to_string(n_bytes)) 10 | self.assertEqual(bytes_to_string(0), "0B", "0 bytes should result in \"0B\"") -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools", 4 | "wheel", 5 | "numpy>=1.10", 6 | "Cython>=0.22", 7 | "scipy", 8 | "mdtraj", 9 | "pybind11", 10 | "deeptime", 11 | ] 12 | 13 | 14 | # TODO: investigate: this does not ship versioneer.py from project root. 15 | #build-backend = "setuptools.build_meta" 16 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | 2 | [tool:pytest] 3 | addopts= --doctest-modules 4 | doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL 5 | usefixtures=session_fixture 6 | norecursedirs=_ext/orderedset _ext/sklearn 7 | filterwarnings = 8 | once::DeprecationWarning 9 | once::PendingDeprecationWarning 10 | ignore:.*Returning plain coordinates.*:UserWarning 11 | 12 | [alias] 13 | test=pytest 14 | 15 | 16 | # See the docstring in versioneer.py for instructions. Note that you must 17 | # re-run 'versioneer.py setup' after changing this section, and commit the 18 | # resulting files. 19 | 20 | [versioneer] 21 | VCS = git 22 | style = pep440 23 | versionfile_source = pyemma/_version.py 24 | versionfile_build = pyemma/_version.py 25 | tag_prefix = v 26 | parentdir_prefix = pyemma- 27 | 28 | --------------------------------------------------------------------------------