Copy disabled (too large)
Download .txt
Showing preview only (46,302K chars total). Download the full file to get everything.
Repository: choderalab/perses
Branch: main
Commit: c716ba936fff
Files: 291
Total size: 64.6 MB
Directory structure:
gitextract_2hkw0qsl/
├── .codecov.yml
├── .gitattributes
├── .github/
│ ├── pull_request_template.md
│ └── workflows/
│ ├── CI.yaml
│ ├── docker.yaml
│ ├── rc-check.yaml
│ ├── rc-test.yaml
│ └── self-hosted-gpu-test.yml
├── .gitignore
├── CITATION.cff
├── LICENSE
├── MANIFEST.in
├── README.md
├── basesetup.py
├── benchmarks/
│ ├── LSF-job-template.sh
│ ├── README.md
│ ├── benchmark_analysis.py
│ ├── run_benchmarks.py
│ └── template.yaml
├── devtools/
│ ├── README.md
│ ├── conda-envs/
│ │ └── test_env.yaml
│ ├── scripts/
│ │ └── initialize_conda.sh
│ └── test.smi
├── docker/
│ ├── Dockerfile
│ ├── Dockerfile-add-license
│ └── README.md
├── docs/
│ ├── Makefile
│ ├── _static/
│ │ └── README.md
│ ├── analysis.rst
│ ├── annihilation.rst
│ ├── bias.rst
│ ├── changelog.rst
│ ├── conf.py
│ ├── environment.yml
│ ├── examples.rst
│ ├── index.rst
│ ├── installation.rst
│ ├── rjmc.rst
│ ├── samplers.rst
│ └── storage.rst
├── examples/
│ ├── README.md
│ ├── atom-mapping/
│ │ └── Atom-mapping.ipynb
│ ├── barnase-barstar-neq-switching/
│ │ ├── README.md
│ │ └── run_example.py
│ ├── dipeptide-mutation-repex-rest/
│ │ ├── README.md
│ │ ├── configfile
│ │ ├── generate_htfs.py
│ │ ├── hostfile
│ │ └── run_repex.py
│ ├── dipeptide-neq-switching/
│ │ ├── README.md
│ │ └── run_example.py
│ ├── kinase-neq-switching/
│ │ ├── README.md
│ │ └── run_example.py
│ ├── moonshot-mainseries/
│ │ ├── 00-prep-receptor.py
│ │ ├── 01-simulate-receptors.py
│ │ ├── 02-generate-poses-posit.py
│ │ ├── 02-generate-poses.py
│ │ ├── 03-list-absent-molecules.py
│ │ ├── README.md
│ │ ├── molecules/
│ │ │ ├── CDD CSV Export.csv
│ │ │ ├── filter-cdd-export.py
│ │ │ ├── mainseries.csv
│ │ │ ├── step1.csv
│ │ │ ├── step2.csv
│ │ │ ├── step3.csv
│ │ │ └── step4.csv
│ │ ├── perses/
│ │ │ ├── analyze-benchmark-pKa.py
│ │ │ ├── extract-trajectories.py
│ │ │ ├── run-perses.py
│ │ │ ├── submit-all.sh
│ │ │ └── template.yaml
│ │ └── setup.yaml
│ └── protein-ligand-repex/
│ └── cli/
│ ├── README.md
│ ├── protein-ligand.yaml
│ ├── scripts_utils/
│ │ ├── cleanup.sh
│ │ ├── run_star_map.sh
│ │ ├── submit-dense-map.sh
│ │ └── submit-star-map-serial.sh
│ ├── tyk2_ligands.sdf
│ └── tyk2_protein.pdb
├── notebooks/
│ ├── Analyze_results.ipynb
│ ├── Harmonic oscillators example.ipynb
│ ├── README.md
│ └── plotting_tools.py
├── notes/
│ ├── README.md
│ ├── chodera-research.bib
│ ├── manuscript.tex
│ └── prsty.bst
├── perses/
│ ├── README.md
│ ├── __init__.py
│ ├── _version.py
│ ├── analysis/
│ │ ├── __init__.py
│ │ ├── analyse_sams_convergence.py
│ │ ├── analysis.py
│ │ ├── analyze-profile.py
│ │ ├── cycles.py
│ │ ├── extract_trajectory.py
│ │ ├── fah_analysis.py
│ │ ├── generate-protonated-termini.py
│ │ ├── load_simulations.py
│ │ ├── resample.py
│ │ ├── utils.py
│ │ └── visualization.py
│ ├── annihilation/
│ │ ├── __init__.py
│ │ ├── lambda_protocol.py
│ │ ├── ncmc_switching.py
│ │ ├── relative.py
│ │ └── rest.py
│ ├── app/
│ │ ├── __init__.py
│ │ ├── cli.py
│ │ ├── fah_generator.py
│ │ ├── relative_hydration.py
│ │ ├── relative_point_mutation_setup.py
│ │ ├── relative_setup.py
│ │ └── setup_relative_calculation.py
│ ├── bias/
│ │ ├── __init__.py
│ │ └── bias_engine.py
│ ├── data/
│ │ ├── 181L.pdb
│ │ ├── 1sb0.pdb
│ │ ├── 8mer-example/
│ │ │ └── 4zuh_peptide_capped.pdb
│ │ ├── L99A-binders.txt
│ │ ├── L99A-non-binders.txt
│ │ ├── T4-inhibitors.xml
│ │ ├── Tyk2_ligands_example/
│ │ │ ├── Tyk2_ligands_shifted.sdf
│ │ │ ├── Tyk2_protein.pdb
│ │ │ └── tyk2_0_3.yaml
│ │ ├── abl-imatinib/
│ │ │ ├── README.md
│ │ │ ├── complex.pdb
│ │ │ ├── inhibitor.pdb
│ │ │ └── receptor.pdb
│ │ ├── abl-src/
│ │ │ ├── abl-imatinib.pdb
│ │ │ └── src-imatinib.pdb
│ │ ├── ala_vacuum.pdb
│ │ ├── amber99sbildn-valence-only.xml
│ │ ├── amino_acid_templates/
│ │ │ ├── ALA.pdb
│ │ │ ├── ARG.pdb
│ │ │ ├── ASH.pdb
│ │ │ ├── ASN.pdb
│ │ │ ├── ASP.pdb
│ │ │ ├── CYS.pdb
│ │ │ ├── GLH.pdb
│ │ │ ├── GLN.pdb
│ │ │ ├── GLU.pdb
│ │ │ ├── GLY.pdb
│ │ │ ├── HID.pdb
│ │ │ ├── HIE.pdb
│ │ │ ├── HIP.pdb
│ │ │ ├── HIS.pdb
│ │ │ ├── ILE.pdb
│ │ │ ├── LEU.pdb
│ │ │ ├── LYN.pdb
│ │ │ ├── LYS.pdb
│ │ │ ├── MET.pdb
│ │ │ ├── PHE.pdb
│ │ │ ├── PRO.pdb
│ │ │ ├── SER.pdb
│ │ │ ├── THR.pdb
│ │ │ ├── TRP.pdb
│ │ │ ├── TYR.pdb
│ │ │ └── VAL.pdb
│ │ ├── arg_solvated.cif
│ │ ├── bace-example/
│ │ │ ├── Bace_ligands_shifted.sdf
│ │ │ ├── Bace_protein.pdb
│ │ │ ├── TLA.sdf
│ │ │ └── bace_setup.yaml
│ │ ├── barstar-mutation/
│ │ │ ├── 1brs_barnase_renumbered.pdb
│ │ │ ├── 1brs_barstar_renumbered.pdb
│ │ │ ├── mmc2_barnase.pdb
│ │ │ ├── mmc2_barstar.pdb
│ │ │ └── mutant.yaml
│ │ ├── cdk2-example/
│ │ │ ├── CDK2_fixed_nohet.pdb
│ │ │ ├── CDK2_ligands.sdf
│ │ │ ├── CDK2_ligands_shifted.sdf
│ │ │ ├── CDK2_protein.pdb
│ │ │ ├── README.md
│ │ │ ├── cdk2-cache.json
│ │ │ ├── cdk2_setup_neq.yaml
│ │ │ └── cdk2_setup_repex.yaml
│ │ ├── clinical-kinase-inhibitors.csv
│ │ ├── constant-pH/
│ │ │ ├── abl-imatinib/
│ │ │ │ ├── Imatinib-epik-charged.ffxml
│ │ │ │ ├── Imatinib-epik-charged.mol2
│ │ │ │ ├── Imatinib-state-penalties.out
│ │ │ │ ├── README.md
│ │ │ │ ├── complex.pdb
│ │ │ │ ├── generate-ligand-ffxml.py
│ │ │ │ ├── inhibitor.pdb
│ │ │ │ └── receptor.pdb
│ │ │ └── imidazole/
│ │ │ ├── README.md
│ │ │ ├── convert.py
│ │ │ ├── generate-protomers-from-smiles.py
│ │ │ ├── imidazole/
│ │ │ │ ├── imidazole-epik-charged.mol2
│ │ │ │ ├── imidazole-epik-charged.pdb
│ │ │ │ ├── imidazole-epik.mae
│ │ │ │ ├── imidazole-epik.mol2
│ │ │ │ ├── imidazole-epik.sdf
│ │ │ │ ├── imidazole-input.mol2
│ │ │ │ └── imidazole-state-penalties.out
│ │ │ └── imidazole.pdb
│ │ ├── constrained-to-unconstrained/
│ │ │ └── ligands_constraint_test.sdf
│ │ ├── gaff-valence-only.xml
│ │ ├── gaff.xml
│ │ ├── gaff2.xml
│ │ ├── generate_gaff_xml.py
│ │ ├── given-geometries/
│ │ │ ├── README.md
│ │ │ ├── ligands.sdf
│ │ │ └── receptor.pdb
│ │ ├── host-guest/
│ │ │ ├── a1.sybyl.mol2
│ │ │ ├── a2.sybyl.mol2
│ │ │ ├── cache.json
│ │ │ └── cb7.sybyl.mol2
│ │ ├── kinase-inhibitors.xml
│ │ ├── kinase-mutation/
│ │ │ ├── NTRK1.pdb
│ │ │ └── entrectinib.sdf
│ │ ├── lys_solvated.cif
│ │ ├── protein.ff14SB.protonated-termini.xml
│ │ ├── protein.ff14SB.xml
│ │ ├── schrodinger-jacs-datasets/
│ │ │ ├── Bace_ligands.sdf
│ │ │ ├── CDK2_ligands.sdf
│ │ │ ├── Jnk1_ligands.sdf
│ │ │ ├── MCL1_ligands.sdf
│ │ │ ├── PTP1B_ligands.sdf
│ │ │ ├── README.md
│ │ │ ├── Thrombin_ligands.sdf
│ │ │ ├── Tyk2_ligands.sdf
│ │ │ └── p38_ligands.sdf
│ │ ├── test.smi
│ │ ├── thr_vacuum.pdb
│ │ └── visualization/
│ │ ├── protein-mutation/
│ │ │ ├── new.dcd
│ │ │ ├── new.pdb
│ │ │ ├── old.dcd
│ │ │ └── old.pdb
│ │ └── small-molecule/
│ │ ├── new.dcd
│ │ ├── new.pdb
│ │ ├── old.dcd
│ │ └── old.pdb
│ ├── dispersed/
│ │ ├── __init__.py
│ │ ├── feptasks.py
│ │ ├── parallel.py
│ │ ├── smc.py
│ │ └── utils.py
│ ├── rjmc/
│ │ ├── __init__.py
│ │ ├── atom_mapping.py
│ │ ├── coordinate_numba.py
│ │ ├── coordinate_tools.py
│ │ ├── geometry.py
│ │ └── topology_proposal.py
│ ├── samplers/
│ │ ├── __init__.py
│ │ ├── multistate.py
│ │ ├── samplers.py
│ │ └── thermodynamics.py
│ ├── storage/
│ │ ├── __init__.py
│ │ ├── movie.py
│ │ └── storage.py
│ ├── tests/
│ │ ├── __init__.py
│ │ ├── benchmark.py
│ │ ├── conftest.py
│ │ ├── test_GPU.py
│ │ ├── test_analysis.py
│ │ ├── test_atom_mapping.py
│ │ ├── test_cli.py
│ │ ├── test_coordinate_numba.py
│ │ ├── test_fah.py
│ │ ├── test_geometry_engine.py
│ │ ├── test_lambda_protocol.py
│ │ ├── test_ncmc_integrator.py
│ │ ├── test_parallel.py
│ │ ├── test_relative.py
│ │ ├── test_relative_point_mutation_setup.py
│ │ ├── test_relative_setup.py
│ │ ├── test_repex.py
│ │ ├── test_rest.py
│ │ ├── test_resume.py
│ │ ├── test_samplers.py
│ │ ├── test_smc.py
│ │ ├── test_storage.py
│ │ ├── test_topology_proposal.py
│ │ ├── test_utils.py
│ │ ├── test_visualization.py
│ │ ├── testsystems.py
│ │ └── utils.py
│ └── utils/
│ ├── __init__.py
│ ├── charge_changing.py
│ ├── data.py
│ ├── openeye.py
│ ├── smallmolecules.py
│ └── url_utils.py
├── readthedocs.yml
├── setup.cfg
├── setup.py
├── spec-file.txt
└── versioneer.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .codecov.yml
================================================
# Codecov configuration to make it a bit less noisy
coverage:
status:
patch: false
project:
default:
threshold: 50%
comment:
layout: "header"
require_changes: false
branches: null
behavior: default
flags: null
paths: null
================================================
FILE: .gitattributes
================================================
perses/_version.py export-subst
================================================
FILE: .github/pull_request_template.md
================================================
## Description
<!-- Describe your changes in detail. -->
## Motivation and context
<!--- Why is this change required? What problem does it solve? -->
<!-- Replace ??? with the issue number that this pull request resolves. -->
Resolves #???
## How has this been tested?
<!--- Please describe in detail how you tested your changes. -->
## Change log
<!-- Propose a change log entry. -->
<!-- Examples here https://github.com/choderalab/perses/blob/master/docs/changelog.rst -->
```
```
================================================
FILE: .github/workflows/CI.yaml
================================================
name: CI
on:
merge_group:
pull_request:
branches:
- "main"
- "0.10.*"
schedule:
# nightly tests
- cron: "0 0 * * *"
push:
branches:
- main
- "0.10.x"
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
test:
name: Test on ubuntu-latest, Python ${{ matrix.python-version }}, OpenMM ${{ matrix.openmm }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.9, "3.10"]
openmm: ["8.0", "7.7"]
include:
- openmm: "dev"
python-version: "3.10"
env:
OPENMM: ${{ matrix.openmm }}
OE_LICENSE: ${{ github.workspace }}/oe_license.txt
steps:
- uses: actions/checkout@v2
- name: Additional info about the build
shell: bash
run: |
uname -a
df -h
ulimit -a
- name: Setup micromamba dev
if: ${{ matrix.openmm == 'dev' }}
uses: mamba-org/provision-with-micromamba@main
with:
environment-file: devtools/conda-envs/test_env.yaml
environment-name: test
channels: jaimergp/label/unsupported-cudatoolkit-shim,conda-forge/label/openmm_dev,conda-forge,openeye
channel-priority: flexible
cache-env: true
cache-downloads: true
extra-specs: |
python==${{ matrix.python-version }}
openmmtools==0.23.0
openmm==8.0.0dev3
- name: Setup micromamba
if: ${{ matrix.openmm != 'dev' }}
uses: mamba-org/provision-with-micromamba@main
with:
environment-file: devtools/conda-envs/test_env.yaml
environment-name: test
cache-env: true
cache-downloads: true
extra-specs: |
python==${{ matrix.python-version }}
openmm==${{ matrix.openmm }}
- name: Install package
shell: bash -l {0}
run: |
python -m pip install --no-deps -v .
- name: Environment Information
shell: bash -l {0}
run: |
micromamba info
micromamba list
- name: Decrypt OpenEye license
shell: bash -l {0}
env:
OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }}
run: |
echo "${OE_LICENSE_TEXT}" > ${OE_LICENSE}
python -c "import openeye; assert openeye.oechem.OEChemIsLicensed(), 'OpenEye license checks failed!'"
- name: Test the package
shell: bash -l {0}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_TEST_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_TEST_SECRET }}
run: |
export TRAVIS=true
pytest -v --cov-report xml --cov=perses --durations=0 -a "not advanced" -n auto -m "not gpu_needed" perses/tests
- name: Codecov
if: ${{ github.repository == 'choderalab/perses'
&& github.event != 'schedule' }}
uses: codecov/codecov-action@v1
with:
file: ./coverage.xml
fail_ci_if_error: false
================================================
FILE: .github/workflows/docker.yaml
================================================
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
name: Create and publish a Docker image
on:
push:
branches:
- feat/improve_docker_building
workflow_dispatch:
defaults:
run:
shell: bash -l {0}
env:
REGISTRY: ghcr.io
IMAGE_NAME: choderalab/perses
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Free disk space
run: |
run: |
sudo docker rmi $(docker image ls -aq) >/dev/null 2>&1 || true
sudo rm -rf \
/usr/share/dotnet /usr/local/lib/android /opt/ghc \
/usr/local/share/powershell /usr/share/swift /usr/local/.ghcup \
/usr/lib/jvm || true
echo "some directories deleted"
sudo apt install aptitude -y >/dev/null 2>&1
sudo aptitude purge aria2 ansible azure-cli shellcheck rpm xorriso zsync \
esl-erlang firefox gfortran-8 gfortran-9 google-chrome-stable \
google-cloud-sdk imagemagick \
libmagickcore-dev libmagickwand-dev libmagic-dev ant ant-optional kubectl \
mercurial apt-transport-https mono-complete libmysqlclient \
unixodbc-dev yarn chrpath libssl-dev libxft-dev \
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev \
snmp pollinate libpq-dev postgresql-client powershell ruby-full \
sphinxsearch subversion mongodb-org azure-cli microsoft-edge-stable \
-y -f >/dev/null 2>&1
sudo aptitude purge google-cloud-sdk -f -y >/dev/null 2>&1
sudo aptitude purge microsoft-edge-stable -f -y >/dev/null 2>&1 || true
sudo apt purge microsoft-edge-stable -f -y >/dev/null 2>&1 || true
sudo aptitude purge '~n ^mysql' -f -y >/dev/null 2>&1
sudo aptitude purge '~n ^php' -f -y >/dev/null 2>&1
sudo aptitude purge '~n ^dotnet' -f -y >/dev/null 2>&1
sudo apt-get autoremove -y >/dev/null 2>&1
sudo apt-get autoclean -y >/dev/null 2>&1
echo "some packages purged"
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get Latest Version
id: latest-version
run: |
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
echo $LATEST_TAG
echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_OUTPUT
# In this case the version is the same as the latest_tag
VERSION=$LATEST_TAG
echo $VERSION
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
- name: Print Latest Version
run: echo ${{ steps.latest-version.outputs.VERSION }}
- name: Create fully qualified image registry path
id: fqirp
run: |
FQIRP=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.latest-version.outputs.VERSION }}
echo "FQIRP=$FQIRP" >> $GITHUB_OUTPUT
- name: Print FQIRP
run: echo ${{ steps.fqirp.outputs.FQIRP }}
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=schedule,pattern=nightly,enable=true,priority=1000
type=ref,event=branch,enable=true,priority=600
type=ref,event=tag,enable=true,priority=600
type=ref,event=pr,prefix=pr-,enable=true,priority=600
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{version}}
type=sha
${{ steps.latest-version.outputs.VERSION }}
latest
- name: Build and export to Docker
uses: docker/build-push-action@v4
with:
context: .
file: docker/Dockerfile
load: true
push: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
VERSION=${{ steps.latest-version.outputs.VERSION }}
- name: Test image
run: |
mkdir oe_license_dir
# Write out license to a file
echo "${{ secrets.OE_LICENSE }}" > oe_license_dir/oe_license.txt
docker run --rm ${{ steps.fqirp.outputs.FQIRP }} perses-cli --help
# Mount oe_license_dir (which should have the license file) to /openeye on container for testing
#docker run -e GITHUB_ACTIONS=true --mount type=bind,source=$PWD/oe_license_dir/,target=/openeye/,readonly --rm ${{ steps.fqirp.outputs.FQIRP }} pytest --pyargs perses -a "not advanced" -n auto -m "not gpu_needed" -v
- name: Push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
file: docker/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
VERSION=${{ steps.latest-version.outputs.VERSION }}
- name: Setup Apptainer
uses: eWaterCycle/setup-apptainer@v2
with:
apptainer-version: 1.1.2
- name: Build Apptainer Image
run: singularity build perses_${{ steps.latest-version.outputs.VERSION }}.sif docker-daemon:${{ steps.fqirp.outputs.FQIRP }}
- name: Test & Push Apptainer Image
run: |
set -e
mkdir test_apptainer
cd test_apptainer
singularity run ../perses_${{ steps.latest-version.outputs.VERSION }}.sif perses-cli --help
#singularity run --bind ../oe_license_dir/:/openeye/ --env "GITHUB_ACTIONS=true" ../perses_${{ steps.latest-version.outputs.VERSION }}.sif pytest --pyargs perses -a "not advanced" -n auto -m "not gpu_needed" -v
echo ${{ secrets.GITHUB_TOKEN }} | singularity remote login -u ${{ secrets.GHCR_USERNAME }} --password-stdin oras://ghcr.io
singularity push ../perses_${{ steps.latest-version.outputs.VERSION }}.sif oras://${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.latest-version.outputs.VERSION }}-apptainer
singularity push ../perses_${{ steps.latest-version.outputs.VERSION }}.sif oras://${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-apptainer
================================================
FILE: .github/workflows/rc-check.yaml
================================================
on:
schedule:
# nightly tests, 2 am
- cron: "0 2 * * *"
jobs:
check-rc:
runs-on: ubuntu-latest
name: "Check for an OpenMM RC"
steps:
- uses: actions/checkout@v2
- uses: dwhswenson/conda-rc-check@main
id: check
with:
channel: conda-forge
package: openmm
ndays: 30
labels: 'main openmm_rc'
- run: echo ${{ steps.check.outputs.hasrc }}
- uses: benc-uk/workflow-dispatch@v1
with:
workflow: OpenMM RC Test
# mikemhenry PAT
# see https://github.com/benc-uk/workflow-dispatch#token
token: ${{ secrets.DISPATCH_TOKEN }}
if: ${{ steps.check.outputs.hasrc == 'True' }}
================================================
FILE: .github/workflows/rc-test.yaml
================================================
name: OpenMM RC Test
on:
workflow_dispatch:
jobs:
rc-test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.8, 3.9]
openmm: ["release candidate"]
env:
OPENMM: ${{ matrix.openmm }}
OE_LICENSE: ${{ github.workspace }}/oe_license.txt
steps:
- uses: actions/checkout@v2
- name: Additional info about the build
shell: bash
run: |
uname -a
df -h
ulimit -a
# More info on options: https://github.com/conda-incubator/setup-miniconda
- uses: conda-incubator/setup-miniconda@v2
with:
python-version: ${{ matrix.python-version }}
environment-file: devtools/conda-envs/test_env.yaml
channels: jaimergp/label/unsupported-cudatoolkit-shim,conda-forge,defaults,omnia-dev,openeye
activate-environment: test
auto-update-conda: true
auto-activate-base: false
show-channel-urls: true
channel-priority: true
miniforge-variant: Mambaforge
- name: Refine test environment
shell: bash -l {0}
run: |
echo "installing OpenMM RC"
mamba install -y -c conda-forge/label/openmm_rc -c conda-forge openmm
- name: Install package
shell: bash -l {0}
run: |
python -m pip install --no-deps -v .
- name: Environment Information
shell: bash -l {0}
run: |
mamba info -a
mamba list
- name: Decrypt OpenEye license
shell: bash -l {0}
env:
OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }}
run: |
echo "${OE_LICENSE_TEXT}" > ${OE_LICENSE}
python -c "import openeye; assert openeye.oechem.OEChemIsLicensed(), 'OpenEye license checks failed!'"
- name: Test the package
shell: bash -l {0}
run: |
export TRAVIS=true
pushd .
pytest -v --cov-report xml --cov=perses --durations=0 -a "not advanced" -n auto -m "not gpu_needed"
popd
================================================
FILE: .github/workflows/self-hosted-gpu-test.yml
================================================
name: self-hosted-gpu-test
on:
push:
branches:
- main
- "0.10.x"
workflow_dispatch:
schedule:
# nightly tests
- cron: "0 0 * * *"
jobs:
start-runner:
name: Start self-hosted EC2 runner
runs-on: ubuntu-latest
outputs:
label: ${{ steps.start-ec2-runner.outputs.label }}
ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }}
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Try to start EC2 runner
id: start-ec2-runner
uses: machulav/ec2-github-runner@main
with:
mode: start
github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
ec2-image-id: ami-04d16a12bbc76ff0b
ec2-instance-type: g4dn.xlarge
subnet-id: subnet-0dee8543e12afe0cd # us-east-1a
security-group-id: sg-0f9809618550edb98
# iam-role-name: self-hosted-runner # optional, requires additional permissions
aws-resource-tags: > # optional, requires additional permissions
[
{"Key": "Name", "Value": "ec2-github-runner"},
{"Key": "GitHubRepository", "Value": "${{ github.repository }}"}
]
do-the-job:
name: Do the job on the runner
needs: start-runner # required to start the main job when the runner is ready
runs-on: ${{ needs.start-runner.outputs.label }} # run the job on the newly created runner
timeout-minutes: 1200 # 20 hrs
env:
TEST_MODE: GPU
OPENMM: 8.0
OE_LICENSE: ${{ github.workspace }}/oe_license.txt
HOME: /home/ec2-user
defaults:
run:
shell: bash -l {0}
steps:
- name: setup env
run: |
echo $HOME
export HOME=/home/ec2-user
echo $HOME
- uses: actions/checkout@v3
- uses: mamba-org/provision-with-micromamba@main
with:
environment-file: devtools/conda-envs/test_env.yaml
channels: conda-forge,openeye
extra-specs: |
python==3.9
openmm>=8.0
cudatoolkit==11.7
pymbar<4
- name: Additional info about the build
run: |
uname -a
df -h
ulimit -a
micromamba info
micromamba list
python -c "import openmm; print(openmm.Platform.getPluginLoadFailures())"
python -m openmm.testInstallation
- name: Install package
run: |
python -m pip install --no-deps -v .
- name: Environment Information
run: |
micromamba info
micromamba list
- name: Decrypt OpenEye license
env:
OE_LICENSE_TEXT: ${{ secrets.OE_LICENSE }}
run: |
echo "${OE_LICENSE_TEXT}" > ${OE_LICENSE}
python -c "import openeye; assert openeye.oechem.OEChemIsLicensed(), 'OpenEye license checks failed!'"
- name: Test the package
run: |
export TRAVIS=true
micromamba list
pytest -v --cov-report xml --cov=perses --durations=0 -a "not advanced" -m "gpu_ci or gpu_needed" perses/tests
- name: Codecov
if: ${{ github.repository == 'choderalab/perses'
&& github.event != 'schedule' }}
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
fail_ci_if_error: false
stop-runner:
name: Stop self-hosted EC2 runner
needs:
- start-runner # required to get output from the start-runner job
- do-the-job # required to wait when the main job is done
runs-on: ubuntu-latest
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Stop EC2 runner
uses: machulav/ec2-github-runner@main
with:
mode: stop
github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
label: ${{ needs.start-runner.outputs.label }}
ec2-instance-id: ${{ needs.start-runner.outputs.ec2-instance-id }}
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
docs/api/generated/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# IDEs
.idea/
.vscode/
# SonarQube
.scannerwork/
================================================
FILE: CITATION.cff
================================================
# This CITATION.cff file was generated with cffinit.
# Visit https://bit.ly/cffinit to generate yours today!
cff-version: 1.2.0
title: Perses
message: Please cite this software using these metadata.
type: software
authors:
- given-names: Dominic A.
family-names: Rufa
orcid: 'https://orcid.org/0000-0003-0930-9445'
- given-names: Ivy
family-names: Zhang
orcid: 'https://orcid.org/0000-0003-0628-6276'
- given-names: Hannah E.
family-names: Bruce Macdonald
orcid: 'https://orcid.org/0000-0002-5562-6866'
- given-names: Patrick B.
family-names: Grinaway
orcid: 'https://orcid.org/0000-0002-9762-4201'
- given-names: Iván
family-names: Pulido
orcid: 'https://orcid.org/0000-0002-7178-8136'
- given-names: Mike M.
family-names: Henry
orcid: 'https://orcid.org/0000-0002-3870-9993'
- given-names: Jaime
family-names: Rodríguez-Guerra
orcid: 'https://orcid.org/0000-0001-8974-1566'
- given-names: Matt
family-names: Wittmann
- given-names: Steven K.
family-names: Albanese
orcid: 'https://orcid.org/0000-0003-0973-5030'
- given-names: William G.
family-names: Glass
orcid: 'https://orcid.org/0000-0002-4099-9280'
- given-names: Ana
family-names: Silveira
orcid: 'https://orcid.org/0000-0002-9419-3397'
- given-names: David
family-names: Schaller
orcid: 'https://orcid.org/0000-0002-1881-4518'
- given-names: Levi N.
family-names: Naden
orcid: 'https://orcid.org/0000-0002-3692-5027'
- given-names: John D.
family-names: Chodera
orcid: 'https://orcid.org/0000-0003-0542-119X'
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2015-2017 Chodera lab // Memorial Sloan Kettering Cancer Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: MANIFEST.in
================================================
include versioneer.py
include perses/_version.py
================================================
FILE: README.md
================================================
<!--- [](https://travis-ci.org/choderalab/perses/branches) --->
[](https://github.com/choderalab/perses/actions?query=branch%3Amaster)
[](https://codecov.io/gh/choderalab/perses/branch/main)
[](http://perses.readthedocs.io/en/latest/?badge=latest)
[](https://zenodo.org/badge/latestdoi/27087846)
# Perses
Experiments with expanded ensemble simulation to explore chemical and mutational space.
## License
This software is licensed under the [MIT license](https://opensource.org/licenses/MIT), a permissive open source license.
## Notice
Please be aware that this code is made available in the spirit of open science, but is currently pre-alpha--that is,
**it is not guaranteed to be completely tested or provide the correct results**, and the API can change at any time
without warning. If you do use this code, do so at your own risk. We appreciate your input, including raising issues
about potential problems with the code, but may not be able to address your issue until other development activities
have concluded.
## Install
See our installation instructions [here](https://perses.readthedocs.io/en/latest/installation.html).
### Quick Start
In a fresh conda environment:
```
$ conda config --add channels conda-forge openeye
$ conda install perses openeye-toolkits
```
## Manifest
* `perses/` - Package containing code for performing expanded ensemble simulations
* `examples/` - Contains examples for various systems and methods of simulation
* `attic/` - some old code that may be useful as part of the new setup
* `devtools/` - Continuous integration and packaging utilities
* `notes/` - LaTeX notes deriving acceptance criteria and stochastic approximation methods
## Contributors
A complete list of contributors can be found at [GitHub Insights](https://github.com/choderalab/perses/graphs/contributors).
Major contributors include:
* Julie M. Behr
* Hannah E. Bruce Macdonald
* John D. Chodera
* Patrick B. Grinaway
* Mike M. Henry
* Iván J. Pulido
* Jaime Rodríguez-Guerra
* Dominic A. Rufa
* Ivy Zhang
## Cite
Please consider citing:
* **Software**:
Rufa, D. A., Zhang, I., Bruce Macdonald, H. E., Grinaway, P. B., Pulido, I., Henry, M. M., Rodríguez-Guerra, J., Wittmann, M., Albanese, S. K., Glass, W. G., Silveira, A., Schaller, D., Naden, L. N., & Chodera, J. D. (2023). Perses (0.10.3). Zenodo. https://doi.org/10.5281/zenodo.8350218
* **Protein mutations**:
Zhang, I., Rufa, D. A., Pulido, I., Henry, M. M., Rosen, L. E., Hauser, K., Singh, S., & Chodera, J. D. (2023). Identifying and Overcoming the Sampling Challenges in Relative Binding Free Energy Calculations of a Model Protein:Protein Complex. Journal of chemical theory and computation, 19(15), 4863–4882. https://doi.org/10.1021/acs.jctc.3c00333
* **Small molecule transformations**:
Rufa, D. A., Bruce Macdonald, H. E., Fass, J., Wieder, M., Grinaway, P. B., Roitberg, A. E., Isayev, O., & Chodera, J. D. (2020). Towards chemical accuracy for alchemical free energy calculations with hybrid physics-based machine learning / molecular mechanics potentials. In bioRxiv (p. 2020.07.29.227959). https://doi.org/10.1101/2020.07.29.227959
================================================
FILE: basesetup.py
================================================
from __future__ import print_function, absolute_import
import os
import sys
import imp
import json
import shutil
import subprocess
import tempfile
from distutils.dep_util import newer_group
from distutils.core import Extension
from distutils.errors import DistutilsExecError
from distutils.ccompiler import new_compiler
from distutils.sysconfig import customize_compiler, get_config_vars
from distutils.command.build_ext import build_ext as _build_ext
def find_packages():
"""Find all of mdtraj's python packages.
Adapted from IPython's setupbase.py. Copyright IPython
contributors, licensed under the BSD license.
"""
packages = ['mdtraj.scripts']
for dir,subdirs,files in os.walk('MDTraj'):
package = dir.replace(os.path.sep, '.')
if '__init__.py' not in files:
# not a package
continue
packages.append(package.replace('MDTraj', 'mdtraj'))
return packages
def check_dependencies(dependencies):
def module_exists(dep):
try:
imp.find_module(dep)
return True
except ImportError:
return False
for dep in dependencies:
if len(dep) == 1:
import_name, pkg_name = dep[0], dep[0]
elif len(dep) == 2:
import_name, pkg_name = dep
else:
raise ValueError(dep)
if not module_exists(import_name):
lines = [
'-' * 50,
'Warning: This package requires %r. Try' % import_name,
'',
' $ conda install %s' % pkg_name,
'',
'or:',
'',
' $ pip install %s' % pkg_name,
'-' * 50,
]
print(os.linesep.join(lines), file=sys.stderr)
################################################################################
# Detection of compiler capabilities
################################################################################
class CompilerDetection(object):
# Necessary for OSX. See https://github.com/mdtraj/mdtraj/issues/576
# The problem is that distutils.sysconfig.customize_compiler()
# is necessary to properly invoke the correct compiler for this class
# (otherwise the CC env variable isn't respected). Unfortunately,
# distutils.sysconfig.customize_compiler() DIES on OSX unless some
# appropriate initialization routines have been called. This line
# has a side effect of calling those initialzation routes, and is therefor
# necessary for OSX, even though we don't use the result.
_DONT_REMOVE_ME = get_config_vars()
def __init__(self, disable_openmp):
cc = new_compiler()
customize_compiler(cc)
self.msvc = cc.compiler_type == 'msvc'
self._print_compiler_version(cc)
if disable_openmp:
self.openmp_enabled = False
else:
self.openmp_enabled, openmp_needs_gomp = self._detect_openmp()
self.sse3_enabled = self._detect_sse3() if not self.msvc else True
self.sse41_enabled = self._detect_sse41() if not self.msvc else True
self.compiler_args_sse2 = ['-msse2'] if not self.msvc else ['/arch:SSE2']
self.compiler_args_sse3 = ['-mssse3'] if (self.sse3_enabled and not self.msvc) else []
self.compiler_args_sse41, self.define_macros_sse41 = [], []
if self.sse41_enabled:
self.define_macros_sse41 = [('__SSE4__', 1), ('__SSE4_1__', 1)]
if not self.msvc:
self.compiler_args_sse41 = ['-msse4']
if self.openmp_enabled:
self.compiler_libraries_openmp = []
if self.msvc:
self.compiler_args_openmp = ['/openmp']
else:
self.compiler_args_openmp = ['-fopenmp']
if openmp_needs_gomp:
self.compiler_libraries_openmp = ['gomp']
else:
self.compiler_libraries_openmp = []
self.compiler_args_openmp = []
if self.msvc:
self.compiler_args_opt = ['/O2']
else:
self.compiler_args_opt = ['-O3', '-funroll-loops']
print()
def _print_compiler_version(self, cc):
print("C compiler:")
try:
if self.msvc:
if not cc.initialized:
cc.initialize()
cc.spawn([cc.cc])
else:
cc.spawn([cc.compiler[0]] + ['-v'])
except DistutilsExecError:
pass
def hasfunction(self, funcname, include=None, libraries=None, extra_postargs=None):
# running in a separate subshell lets us prevent unwanted stdout/stderr
part1 = '''
from __future__ import print_function
import os
import json
from distutils.ccompiler import new_compiler
from distutils.sysconfig import customize_compiler, get_config_vars
FUNCNAME = json.loads('%(funcname)s')
INCLUDE = json.loads('%(include)s')
LIBRARIES = json.loads('%(libraries)s')
EXTRA_POSTARGS = json.loads('%(extra_postargs)s')
''' % {
'funcname': json.dumps(funcname),
'include': json.dumps(include),
'libraries': json.dumps(libraries or []),
'extra_postargs': json.dumps(extra_postargs)}
part2 = '''
get_config_vars() # DON'T REMOVE ME
cc = new_compiler()
customize_compiler(cc)
for library in LIBRARIES:
cc.add_library(library)
status = 0
try:
with open('func.c', 'w') as f:
if INCLUDE is not None:
f.write('#include %s\\n' % INCLUDE)
f.write('int main(void) {\\n')
f.write(' %s;\\n' % FUNCNAME)
f.write('}\\n')
objects = cc.compile(['func.c'], output_dir='.',
extra_postargs=EXTRA_POSTARGS)
cc.link_executable(objects, 'a.out')
except Exception as e:
status = 1
exit(status)
'''
tmpdir = tempfile.mkdtemp(prefix='hasfunction-')
try:
curdir = os.path.abspath(os.curdir)
os.chdir(tmpdir)
with open('script.py', 'w') as f:
f.write(part1 + part2)
proc = subprocess.Popen(
[sys.executable, 'script.py'],
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
proc.communicate()
status = proc.wait()
finally:
os.chdir(curdir)
shutil.rmtree(tmpdir)
return status == 0
def _print_support_start(self, feature):
print('Attempting to autodetect {0:6} support...'.format(feature), end=' ')
def _print_support_end(self, feature, status):
if status is True:
print('Compiler supports {0}'.format(feature))
else:
print('Did not detect {0} support'.format(feature))
def _detect_openmp(self):
self._print_support_start('OpenMP')
hasopenmp = self.hasfunction('omp_get_num_threads()', extra_postargs=['-fopenmp', '/openmp'])
needs_gomp = hasopenmp
if not hasopenmp:
hasopenmp = self.hasfunction('omp_get_num_threads()', libraries=['gomp'])
needs_gomp = hasopenmp
self._print_support_end('OpenMP', hasopenmp)
return hasopenmp, needs_gomp
def _detect_sse3(self):
"Does this compiler support SSE3 intrinsics?"
self._print_support_start('SSE3')
result = self.hasfunction('__m128 v; _mm_hadd_ps(v,v)',
include='<pmmintrin.h>',
extra_postargs=['-msse3'])
self._print_support_end('SSE3', result)
return result
def _detect_sse41(self):
"Does this compiler support SSE4.1 intrinsics?"
self._print_support_start('SSE4.1')
result = self.hasfunction( '__m128 v; _mm_round_ps(v,0x00)',
include='<smmintrin.h>',
extra_postargs=['-msse4'])
self._print_support_end('SSE4.1', result)
return result
################################################################################
# Writing version control information to the module
################################################################################
def git_version():
# Return the git revision as a string
# copied from numpy setup.py
def _minimal_ext_cmd(cmd):
# construct minimal environment
env = {}
for k in ['SYSTEMROOT', 'PATH']:
v = os.environ.get(k)
if v is not None:
env[k] = v
# LANGUAGE is used on win32
env['LANGUAGE'] = 'C'
env['LANG'] = 'C'
env['LC_ALL'] = 'C'
out = subprocess.Popen(
cmd, stdout=subprocess.PIPE, env=env).communicate()[0]
return out
try:
out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'])
GIT_REVISION = out.strip().decode('ascii')
except OSError:
GIT_REVISION = 'Unknown'
return GIT_REVISION
def write_version_py(VERSION, ISRELEASED, filename='MDTraj/version.py'):
cnt = """
# THIS FILE IS GENERATED FROM MDTRAJ SETUP.PY
short_version = '%(version)s'
version = '%(version)s'
full_version = '%(full_version)s'
git_revision = '%(git_revision)s'
release = %(isrelease)s
if not release:
version = full_version
"""
# Adding the git rev number needs to be done inside write_version_py(),
# otherwise the import of numpy.version messes up the build under Python 3.
FULLVERSION = VERSION
if os.path.exists('.git'):
GIT_REVISION = git_version()
else:
GIT_REVISION = 'Unknown'
if not ISRELEASED:
FULLVERSION += '.dev-' + GIT_REVISION[:7]
a = open(filename, 'w')
try:
a.write(cnt % {'version': VERSION,
'full_version': FULLVERSION,
'git_revision': GIT_REVISION,
'isrelease': str(ISRELEASED)})
finally:
a.close()
class StaticLibrary(Extension):
def __init__(self, *args, **kwargs):
self.export_include = kwargs.pop('export_include', [])
Extension.__init__(self, *args, **kwargs)
class build_ext(_build_ext):
def build_extension(self, ext):
if isinstance(ext, StaticLibrary):
self.build_static_extension(ext)
else:
_build_ext.build_extension(self, ext)
def build_static_extension(self, ext):
from distutils import log
sources = ext.sources
if sources is None or not isinstance(sources, (list, tuple)):
raise DistutilsSetupError(
("in 'ext_modules' option (extension '%s'), " +
"'sources' must be present and must be " +
"a list of source filenames") % ext.name)
sources = list(sources)
ext_path = self.get_ext_fullpath(ext.name)
depends = sources + ext.depends
if not (self.force or newer_group(depends, ext_path, 'newer')):
log.debug("skipping '%s' extension (up-to-date)", ext.name)
return
else:
log.info("building '%s' extension", ext.name)
extra_args = ext.extra_compile_args or []
macros = ext.define_macros[:]
for undef in ext.undef_macros:
macros.append((undef,))
objects = self.compiler.compile(sources,
output_dir=self.build_temp,
macros=macros,
include_dirs=ext.include_dirs,
debug=self.debug,
extra_postargs=extra_args,
depends=ext.depends)
self._built_objects = objects[:]
if ext.extra_objects:
objects.extend(ext.extra_objects)
extra_args = ext.extra_link_args or []
language = ext.language or self.compiler.detect_language(sources)
libname = os.path.splitext(os.path.basename(ext_path))[0]
output_dir = os.path.dirname(ext_path)
if (self.compiler.static_lib_format.startswith('lib') and
libname.startswith('lib')):
libname = libname[3:]
if not os.path.exists(output_dir):
# necessary for windows
os.makedirs(output_dir)
self.compiler.create_static_lib(objects,
output_libname=libname,
output_dir=output_dir,
target_lang=language)
for item in ext.export_include:
shutil.copy(item, output_dir)
================================================
FILE: benchmarks/LSF-job-template.sh
================================================
#!/bin/bash
#BSUB -P "tyk2-benchmark"
#BSUB -J "perses-benchmark-[1-24]"
#BSUB -n 1
#BSUB -R rusage[mem=8]
#BSUB -R span[hosts=1]
#BSUB -q gpuqueue
#BSUB -sp 1 # low priority. default is 12, max is 25
#BSUB -gpu num=1:j_exclusive=yes:mode=shared
#BSUB -W 24:00
#BSUB -m "lu-gpu lg-gpu lv-gpu ld-gpu lt-gpu lp-gpu ls-gpu lx-gpu ly-gpu ll-gpu boson"
#BSUB -o out_%J_%I.stdout
#BSUB -eo out_%J_%I.stderr
#BSUB -L /bin/bash
source ~/.bashrc
OPENMM_CPU_THREADS=1
echo "changing directory to ${LS_SUBCWD}"
cd $LS_SUBCWD
conda activate perses-dev
# Report node in use
hostname
# Report CUDA info
env | sort | grep 'CUDA'
# launching a benchmark pair (target, edge) per job (0-based thus substract 1)
python run_benchmarks.py --target tyk2 --edge $(( $LSB_JOBINDEX - 1 ))
================================================
FILE: benchmarks/README.md
================================================
# Perses benchmarks
This subdirectory exposes a CLI tool for running automated benchmarks from
[OpenFF's protein ligand benchmark dataset](https://github.com/openforcefield/protein-ligand-benchmark) using perses.
## Running benchmarks
Assuming you have a clone of the perses code repository and you are standing in the `benchmarks` subdirectory
(where this file lives). Then the benchmarks can be run using the following command syntax:
```bash
python run_benchmarks.py --target [protein-name] --edge [edge-index]
```
For example, for running the seventh edge (zero-based, according to [plbenchmark data](https://github.com/openforcefield/protein-ligand-benchmark) )
for `tyk2` protein, you would run:
```bash
# Set up and run edge 6
python run_benchmarks.py --target tyk2 --edge 6
```
Should the calculation for an edge fail, you can simply re-run the same command-line and the calculation will resume:
```bash
# Resume failed edge 6
python run_benchmarks.py --target tyk2 --edge 6
```
For more information on how to use the tool, you can run `python run_benchmarks.py -h`.
## Analyzing benchmarks
To analyze the simulations a script called `benchmark_analysis.py` is used as follows:
```bash
python benchmark_analysis.py --target [protein-name]
```
For example, for tyk2 results:
```bash
python benchmark_analysis.py --target tyk2
```
This will generate an output CSV file for [`arsenic`](https://github.com/openforcefield/arsenic) and corresponding absolute and relative free energy plots as PNG files produced according to best practices.)
For more information on how to use the cli analysis tool use `python benchmark_analysis.py -h`.
================================================
FILE: benchmarks/benchmark_analysis.py
================================================
"""
Script to perform analysis of perses simulations executed using run_benchmarks.py script.
Intended to be used on systems from https://github.com/openforcefield/protein-ligand-benchmark
"""
import argparse
import glob
import itertools
import re
import warnings
import numpy as np
import urllib.request
import yaml
from openmmtools.constants import kB
from perses.analysis.load_simulations import Simulation
from simtk import unit
from openff.arsenic import plotting, wrangle
# global variables
base_repo_url = "https://github.com/openforcefield/protein-ligand-benchmark"
# Helper functions
def get_simdir_list(base_dir='.', is_reversed=False):
"""
Get list of directories to extract simulation data.
Attributes
----------
base_dir: str, optional, default='.'
Base directory where to search for simulations results. Defaults to current directory.
is_reversed: bool, optional, default=False
Whether to consider the reversed simulations or not. Meant for testing purposes.
Returns
-------
dir_list: list
List of directories paths for simulation results.
"""
# Load all expected simulation from directories
out_dirs = ['/'.join(filepath.split('/')[:-1]) for filepath in glob.glob(f'{base_dir}/out*/*complex.nc')]
reg = re.compile(r'out_[0-9]+_[0-9]+_reversed') # regular expression to deal with reversed directories
if is_reversed:
# Choose only reversed directories
out_dirs = list(filter(reg.search, out_dirs))
else:
# Filter out reversed directories
out_dirs = list(itertools.filterfalse(reg.search, out_dirs))
return out_dirs
def get_simulations_data(simulation_dirs):
"""Generates a list of simulation data objects given the simulation directories paths."""
simulations = []
for out_dir in simulation_dirs:
# Load complete or fully working simulations
# TODO: Try getting better exceptions from openmmtools -- use non-generic exceptions
try:
simulation = Simulation(out_dir)
simulations.append(simulation)
except Exception:
warnings.warn(f"Edge in {out_dir} could not be loaded. Check simulation output is complete.")
return simulations
def to_arsenic_csv(experimental_data: dict, simulation_data: list, out_csv: str = 'out_benchmark.csv'):
"""
Generates a csv file to be used with openff-arsenic. Energy units in kcal/mol.
.. warning:: To be deprecated once arsenic object model is improved.
Parameters
----------
experimental_data: dict
Python nested dictionary with experimental data in micromolar or nanomolar units.
Example of entry:
{'lig_ejm_31': {'measurement': {'comment': 'Table 4, entry 31',
'doi': '10.1016/j.ejmech.2013.03.070',
'error': -1,
'type': 'ki',
'unit': 'uM',
'value': 0.096},
'name': 'lig_ejm_31',
'smiles': '[H]c1c(c(c(c(c1[H])Cl)C(=O)N([H])c2c(c(nc(c2[H])N([H])C(=O)C([H])([H])[H])[H])[H])Cl)[H]'}
simulation_data: list or iterable
Python iterable object with perses Simulation objects as entries.
out_csv: str
Path to output csv file to be generated.
"""
# Ligand information
ligands_names = list(ligands_dict.keys())
lig_id_to_name = dict(enumerate(ligands_names))
kBT = kB * 300 * unit.kelvin # useful when converting to kcal/mol
# Write csv file
with open(out_csv, 'w') as csv_file:
# Experimental block
# print header for block
csv_file.write("# Experimental block\n")
csv_file.write("# Ligand, expt_DG, expt_dDG\n")
# Extract ligand name, expt_DG and expt_dDG from ligands dictionary
for ligand_name, ligand_data in experimental_data.items():
# TODO: Handle multiple measurement types
unit_symbol = ligand_data['measurement']['unit']
measurement_value = ligand_data['measurement']['value']
measurement_error = ligand_data['measurement']['error']
# Unit conversion
# TODO: Let's persuade PLBenchmarks to use pint units
unit_conversions = { 'M' : 1.0, 'mM' : 1e-3, 'uM' : 1e-6, 'nM' : 1e-9, 'pM' : 1e-12, 'fM' : 1e-15 }
if unit_symbol not in unit_conversions:
raise ValueError(f'Unknown units "{unit_symbol}"')
value_to_molar= unit_conversions[unit_symbol]
# Handle unknown errors
# TODO: We should be able to ensure that all entries have more reasonable errors.
if measurement_error == -1:
# TODO: For now, we use a relative_error from the Tyk2 system 10.1016/j.ejmech.2013.03.070
relative_error = 0.3
else:
relative_error = measurement_error / measurement_value
# Convert to free eneriges
expt_DG = kBT.value_in_unit(unit.kilocalorie_per_mole) * np.log(measurement_value * value_to_molar)
expt_dDG = kBT.value_in_unit(unit.kilocalorie_per_mole) * relative_error
csv_file.write(f"{ligand_name}, {expt_DG}, {expt_dDG}\n")
# Calculated block
# print header for block
csv_file.write("# Calculated block\n")
csv_file.write("# Ligand1,Ligand2, calc_DDG, calc_dDDG(MBAR), calc_dDDG(additional)\n")
# Loop through simulation, extract ligand1 and ligand2 indices, convert to names, create string with
# ligand1, ligand2, calc_DDG, calc_dDDG(MBAR), calc_dDDG(additional)
# write string in csv file
for simulation in simulation_data:
out_dir = simulation.directory.split('/')[-1]
# getting integer indices
ligand1_id, ligand2_id = int(out_dir.split('_')[-1]), int(out_dir.split('_')[-2]) # CHECK ORDER!
# getting names of ligands
ligand1, ligand2 = lig_id_to_name[ligand1_id], lig_id_to_name[ligand2_id]
# getting calc_DDG in kcal/mol
calc_DDG = simulation.bindingdg.value_in_unit(unit.kilocalorie_per_mole)
# getting calc_dDDG in kcal/mol
calc_dDDG = simulation.bindingddg.value_in_unit(unit.kilocalorie_per_mole)
csv_file.write(
f"{ligand1}, {ligand2}, {calc_DDG}, {calc_dDDG}, 0.0\n") # hardcoding additional error as 0.0
# Defining command line arguments
# fetching targets from github repo
# TODO: This part should be done using plbenchmarks API - once there is a conda pkg
targets_url = f"{base_repo_url}/raw/main/data/targets.yml"
with urllib.request.urlopen(targets_url) as response:
targets_dict = yaml.safe_load(response.read())
# get the possible choices from targets yaml file
target_choices = targets_dict.keys()
arg_parser = argparse.ArgumentParser(description='CLI tool for running perses protein-ligand benchmarks analysis.')
arg_parser.add_argument(
"--target",
type=str,
help="Target biomolecule, use openff's plbenchmark names.",
choices=target_choices,
required=True
)
arg_parser.add_argument(
"--reversed",
action='store_true',
help="Analyze reversed edge simulations. Helpful for testing/consistency checks."
)
args = arg_parser.parse_args()
target = args.target
# Download experimental data
# TODO: This part should be done using plbenchmarks API - once there is a conda pkg
# TODO: Let's cache this data when we set up the initial simulations in case it changes in between setting up and running the calculations and analysis.
# TODO: Let's also be sure to use a specific release tag rather than 'main'
target_dir = targets_dict[target]['dir']
ligands_url = f"{base_repo_url}/raw/main/data/{target_dir}/00_data/ligands.yml"
with urllib.request.urlopen(ligands_url) as response:
yaml_contents = response.read()
print(yaml_contents)
ligands_dict = yaml.safe_load(yaml_contents)
# DEBUG
print('')
print(yaml.dump(ligands_dict))
# Get paths for simulation output directories
out_dirs = get_simdir_list(is_reversed=args.reversed)
# Generate list with simulation objects
simulations = get_simulations_data(out_dirs)
# Generate csv file
csv_path = f'./{target}_arsenic.csv'
to_arsenic_csv(ligands_dict, simulations, out_csv=csv_path)
# TODO: Separate plotting in a different file
# Make plots and store
fe = wrangle.FEMap(csv_path)
# Relative plot
plotting.plot_DDGs(fe.graph,
target_name=f'{target}',
title=f'Relative binding energies - {target}',
figsize=5,
filename='./plot_relative.png'
)
# Absolute plot, with experimental data shifted to correct mean
experimental_mean_dg = np.asarray([node[1]["exp_DG"] for node in fe.graph.nodes(data=True)]).mean()
plotting.plot_DGs(fe.graph,
target_name=f'{target}',
title=f'Absolute binding energies - {target}',
figsize=5,
filename='./plot_absolute.png',
shift=experimental_mean_dg,
)
================================================
FILE: benchmarks/run_benchmarks.py
================================================
#!/usr/bin/env python
"""
CLI utility to automatically run benchmarks using data from the open force field protein-ligand benchmark at
https://github.com/openforcefield/protein-ligand-benchmark
It requires internet connection to function properly, by connecting to the mentioned repository.
"""
# TODO: Use plbenchmarks when conda package is available.
import argparse
import logging
import os
import yaml
from perses.app.setup_relative_calculation import run
from perses.utils.url_utils import retrieve_file_url
from perses.utils.url_utils import fetch_url_contents
# Setting logging level config
LOGLEVEL = os.environ.get("LOGLEVEL", "WARNING").upper()
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=LOGLEVEL,
datefmt='%Y-%m-%d %H:%M:%S')
_logger = logging.getLogger()
_logger.setLevel(LOGLEVEL)
# global variables
base_repo_url = "https://github.com/openforcefield/protein-ligand-benchmark"
def concatenate_files(input_files, output_file):
"""
Concatenate files given in input_files iterator into output_file.
"""
with open(output_file, 'w') as outfile:
for filename in input_files:
with open(filename) as infile:
for line in infile:
outfile.write(line)
def run_relative_perturbation(lig_a_idx, lig_b_idx, reverse=False, tidy=True):
"""
Perform relative free energy simulation using perses CLI.
Parameters
----------
lig_a_idx : int
Index for first ligand (ligand A)
lig_b_idx : int
Index for second ligand (ligand B)
reverse: bool
Run the edge in reverse direction. Swaps the ligands.
tidy : bool, optional
remove auto-generated yaml files.
Expects the target/protein pdb file in the same directory to be called 'target.pdb', and ligands file
to be called 'ligands.sdf'.
"""
_logger.info(f'Starting relative calculation of ligand {lig_a_idx} to {lig_b_idx}')
trajectory_directory = f'out_{lig_a_idx}_{lig_b_idx}'
new_yaml = f'relative_{lig_a_idx}_{lig_b_idx}.yaml'
# read base template yaml file
# TODO: template.yaml file is configured for Tyk2, check if the same options work for others.
with open(f'template.yaml', "r") as yaml_file:
options = yaml.load(yaml_file, Loader=yaml.FullLoader)
# TODO: add a step to perform some minimization - should help with NaNs
# generate yaml file from template
options['protein_pdb'] = 'target.pdb'
options['ligand_file'] = 'ligands.sdf'
if reverse:
# Do the other direction of ligands
options['old_ligand_index'] = lig_b_idx
options['new_ligand_index'] = lig_a_idx
# mark the output directory with reversed
trajectory_directory = f'{trajectory_directory}_reversed'
# mark new yaml file with reversed
temp_path = new_yaml.split('.')
new_yaml = f'{temp_path[0]}_reversed.{temp_path[1]}'
else:
options['old_ligand_index'] = lig_a_idx
options['new_ligand_index'] = lig_b_idx
options['trajectory_directory'] = f'{trajectory_directory}'
with open(new_yaml, 'w') as outfile:
yaml.dump(options, outfile)
# run the simulation - using API point to respect logging level
run(new_yaml)
_logger.info(f'Relative calculation of ligand {lig_a_idx} to {lig_b_idx} complete')
if tidy:
os.remove(new_yaml)
# Defining command line arguments
# fetching targets from github repo
# TODO: This part should be done using plbenchmarks API - once there is a conda pkg
targets_url = f"{base_repo_url}/raw/main/data/targets.yml"
with fetch_url_contents(targets_url) as response:
targets_dict = yaml.safe_load(response.read())
# get the possible choices from targets yaml file
target_choices = targets_dict.keys()
arg_parser = argparse.ArgumentParser(description='CLI tool for running perses protein-ligand benchmarks.')
arg_parser.add_argument(
"--target",
type=str,
help="Target biomolecule, use openff's plbenchmark names.",
choices=target_choices,
required=True
)
arg_parser.add_argument(
"--edge",
type=int,
help="Edge index (0-based) according to edges yaml file in dataset. Ex. --edge 5 (for sixth edge)",
required=True
)
arg_parser.add_argument(
"--reversed",
action='store_true',
help="Whether to run the edge in reverse direction. Helpful for consistency checks."
)
args = arg_parser.parse_args()
target = args.target
is_reversed = args.reversed
# Fetch protein pdb file
# TODO: This part should be done using plbenchmarks API - once there is a conda pkg
target_dir = targets_dict[target]['dir']
pdb_url = f"{base_repo_url}/raw/main/data/{target_dir}/01_protein/crd/protein.pdb"
pdb_file = retrieve_file_url(pdb_url)
# Fetch cofactors crystalwater pdb file
# TODO: This part should be done using plbenchmarks API - once there is a conda pkg
cofactors_url = f"{base_repo_url}/raw/main/data/{target_dir}/01_protein/crd/cofactors_crystalwater.pdb"
cofactors_file = retrieve_file_url(cofactors_url)
# Concatenate protein with cofactors pdbs
concatenate_files((pdb_file, cofactors_file), 'target.pdb')
# Fetch ligands sdf files and concatenate them in one
# TODO: This part should be done using plbenchmarks API - once there is a conda pkg
ligands_url = f"{base_repo_url}/raw/main/data/{target_dir}/00_data/ligands.yml"
with fetch_url_contents(ligands_url) as response:
ligands_dict = yaml.safe_load(response.read())
ligand_files = []
for ligand in ligands_dict.keys():
ligand_url = f"{base_repo_url}/raw/main/data/{target_dir}/02_ligands/{ligand}/crd/{ligand}.sdf"
ligand_file = retrieve_file_url(ligand_url)
ligand_files.append(ligand_file)
# concatenate sdfs
concatenate_files(ligand_files, 'ligands.sdf')
# run simulation
# fetch edges information
# TODO: This part should be done using plbenchmarks API - once there is a conda pkg
edges_url = f"{base_repo_url}/raw/main/data/{target_dir}/00_data/edges.yml"
with fetch_url_contents(edges_url) as response:
edges_dict = yaml.safe_load(response.read())
edges_list = list(edges_dict.values()) # suscriptable edges object - note dicts are ordered for py>=3.7
# edge list to access by index
edge_index = args.edge # read from cli arguments
edge = edges_list[edge_index]
ligand_a_name = edge['ligand_a']
ligand_b_name = edge['ligand_b']
# ligands list to get indices -- preserving same order as upstream yaml file
ligands_list = list(ligands_dict.keys())
lig_a_index = ligands_list.index(ligand_a_name)
lig_b_index = ligands_list.index(ligand_b_name)
# Perform the simulation
run_relative_perturbation(lig_a_index, lig_b_index, reverse=is_reversed)
================================================
FILE: benchmarks/template.yaml
================================================
# Path to protein file
protein_pdb: null
# Path to ligand SDF file
ligand_file: null
# Indices of old and new ligands within SDF file
old_ligand_index: null
new_ligand_index: null
#
# Force fields
#
# OpenMM ffxml force field files installed via the openmm-forcefields package
# for biopolymers and solvents.
# Note that small molecule force field files should NOT be included here.
forcefield_files:
- amber/ff14SB.xml # ff14SB protein force field
- amber/tip3p_standard.xml # TIP3P and recommended monovalent ion parameters
- amber/tip3p_HFE_multivalent.xml # for divalent ions
- amber/phosaa10.xml # HANDLES THE TPO
# Small molecule force field
# Options include anything allowed by the openmmforcefields SystemGenerator
# e.g. one of ['openff-2.0.0', 'gaff-2.11']
small_molecule_forcefield: openff-2.0.0
#
# Simulation conditions
#
# Simulation setup options
solvent_padding: 9.0 # angstroms
# Use geometry-derived mapping
use_given_geometries: true
given_geometries_tolerance: 0.2 # angstroms
# Atom mapping specification
atom_expression:
- IntType
bond_expession:
- DefaultBonds
# Multi-state sampling scheme
# One of ['repex', 'nonequilibrium', 'sams']
fe_type: repex
# Checkpoint interval
checkpoint_interval: 50 # number of iterations
# Number of equilibration iterations
n_equilibration_iterations: 0
# Number of iterations to run
n_cycles: 5000
# Number of alchemical intermediate states to use
n_states: 12
pressure: 1.0 # atmsopheres
temperature: 300.0 # kelvin
timestep: 4.0 # femtoseconds
# remove_constraints: false
# Number of integration stpes per iteration
n_steps_per_move_application: 250
# Location for storing trajectories
trajectory_directory: null
# Prefix for trajectory files (project-specific name)
trajectory_prefix: out
# Atoms to store in NetCDF files (MDTraj selection syntax)
atom_selection: not water
# Calculation phases to run
# Permitted phases: ['complex', 'solvent', 'vacuum']
phases:
- solvent
- complex
================================================
FILE: devtools/README.md
================================================
Developer Notes / Tools
=======================
Assorted notes for developers.
How to do a release
-------------------
First make sure everything is working:
- Make sure CI is passing
- Run GPU tests manually on HPC or the self-hosted EC2 runner on AWS
- Run the PLB (https://github.com/openforcefield/protein-ligand-benchmark)
Then create a new release on github: https://github.com/choderalab/perses/releases/new
Either make a new tag and push it, or select the create a new tag on release option.
Make sure that the change log is detailed and communicates Bugfixes, Enhancements, and New features.
Also attach plots from the PLB in a "Benchmark data" section.
Once the release is posted on github, the conda-forge bot should pick up the release and make a PR to the perses feedstock repository: https://github.com/conda-forge/perses-feedstock
Be sure to update the meta.yaml file with any new dependencies or version pins.
================================================
FILE: devtools/conda-envs/test_env.yaml
================================================
name: test
channels:
- conda-forge
- openeye
dependencies:
- ambertools <23
- arsenic
- autograd
- click
- cloudpathlib-s3 >=0.13.0
- coverage
- dask <2023.5
- dask-jobqueue
- dicttoxml
- distributed
- fire
- joblib
- lxml
- matplotlib
- mdtraj
- netcdf4
- networkx >=2.0
- numba >=0.55.2
- numexpr
- numpy >=1.14
- openeye-toolkits
- openff-toolkit >=0.11.0 # updated to latest
- openff-units >=0.1.8
- openmm >=7.7
- openmmforcefields >=0.9.0
- openmmtools >=0.23 # may need to sort out ambermini/ambertools/parmed dependencies
- openmoltools # may need to sort out ambermini/ambertools/parmed dependencies (we don't want ambertools)
- parmed
- pdbfixer
- pip
- progressbar2
- pymbar
- pytest
- pytest-attrib
- pytest-cov
- pytest-xdist
- python
- rich
- scipy
- seaborn
- setuptools
- sphinx
- tinydb
- tqdm
================================================
FILE: devtools/scripts/initialize_conda.sh
================================================
case $CI_OS in
windows*)
eval "$(${CONDA}/condabin/conda.bat shell.bash hook)";;
*)
eval "$(${CONDA}/condabin/conda shell.bash hook)";;
esac
================================================
FILE: devtools/test.smi
================================================
CCC
CCCC
================================================
FILE: docker/Dockerfile
================================================
FROM mambaorg/micromamba:latest
LABEL org.opencontainers.image.source = "https://github.com/choderalab/perses"
LABEL org.opencontainers.image.description="Experiments with expanded ensemble simulation to explore chemical and mutational space."
LABEL org.opencontainers.image.authors = "John D. Chodera"
LABEL org.opencontainers.image.licenses=MIT
# perses version we want to build
ARG VERSION
# install ps
USER root
RUN apt-get update && apt-get install -y --no-install-recommends \
procps \
&& rm -rf /var/lib/apt/lists/*
USER $MAMBA_USER
# Don't buffer stdout & stderr streams, so if there is a crash no partial buffer output is lost
# https://docs.python.org/3/using/cmdline.html#cmdoption-u
ENV PYTHONUNBUFFERED=1
RUN micromamba install -y -n base -c conda-forge -c openeye openeye-toolkits git pytest-xdist pytest-attrib mpiplus mpich mpi mpi4py clusterutils "perses==$VERSION" cudatoolkit=11.2 && \
micromamba clean --all --yes
# Make directory and tell openeye where to find
# license file
USER root
RUN mkdir /openeye
USER $MAMBA_USER
ENV OE_LICENSE=/openeye/oe_license.txt
# Ensure that conda environment is automatically activated
# https://github.com/mamba-org/micromamba-docker#running-commands-in-dockerfile-within-the-conda-environment
ARG MAMBA_DOCKERFILE_ACTIVATE=1
================================================
FILE: docker/Dockerfile-add-license
================================================
FROM choderalab/perses:dev
ADD oe_license.txt /openeye/
================================================
FILE: docker/README.md
================================================
# Perses Container
The container can be downloaded with `docker pull ghcr.io/choderalab/perses:latest`
## OpenEye License
The open eye license file is not included and must be passed in as a mount point.
The container expects `oe_license.txt` in `/openeye/` because we set `ENV OE_LICENSE=/openeye/oe_license.txt` in the Dockerfile.
To do that use the `--mount` option.
For example, if you have an `oe_license.txt` file in `$HOME/.OpenEye/`.
```
$ docker run --rm --mount type=bind,source=$HOME/.OpenEye/,target=/openeye/,readonly ghcr.io/choderalab/perses:latest python -c "import openeye; assert openeye.oechem.OEChemIsLicensed(), 'OpenEye license checks failed!'"
```
There is also an example file `Dockerfile-add-license` if you want to build a new container with the openeye license file inside it.
If you use this method, be sure to push the container to private locations only.
Anyone with access to the container can extract the license.
## GPU Support
Pass the option `--gpus device=0` to use the host's GPU:
```
$ docker run -it --rm --gpus device=0 --mount type=bind,source=$HOME/.OpenEye/,target=/openeye/,readonly ghcr.io/choderalab/perses:latest python -m simtk.testInstallation
OpenMM Version: 7.5.1
Git Revision: a9cfd7fb9343e21c3dbb76e377c721328830a3ee
There are 3 Platforms available:
1 Reference - Successfully computed forces
2 CPU - Successfully computed forces
3 CUDA - Successfully computed forces
Median difference in forces between platforms:
Reference vs. CPU: 6.29536e-06
Reference vs. CUDA: 6.73195e-06
CPU vs. CUDA: 7.32829e-07
All differences are within tolerance.
```
Note: `perses` currently works best on a single GPU.
See the documentation [here](https://docs.docker.com/config/containers/resource_constraints/#access-an-nvidia-gpu) for how to specify a single GPU on a multi-GPU system.
## Apptainer (formally singularity) image
The apptainer image is pre-built and can be pulled with:
singularity pull oras://ghcr.io/choderalab/perses:latest-apptainer
And can be used like:
```
$ singularity run --nv perses_latest-apptainer.sif python -m openmm.testInstallation
```
## Running perses examples from the container in GPUs using CUDA
If you plan to use our docker container and CUDA/GPUs, quick instructions to get the examples running are as follows.
We have our examples with minimalistic setups to satisfy our current continuous integration (CI) workflow. To get more "realistic" simulations we recommend making the following modifications.
1) Clone the repository (say it lives in `$HOME/repos/perses`) with `git clone https://github.com/choderalab/perses.git`
2) Modify the `run_neq_distrib_flattened.py` inside each of the examples (e.g. `examples/kinase-neq-switching/run_neq_distrib_flattened.py`) you want to run:
- Change the platform name to 'CUDA '(it is CPU by default to satisfy our continuous integration). Should be in line 21 in the script.
- (recommended) You might want to change the nsteps_eq and nsteps_neq (number of steps for equilibrium and nonequilibrium, respectively) to a larger value. Something around 250000 steps (1ns in time) for each should be okay. These should be lines 17 and 18 in the scripts.
- (recommended) Please change the save frequency or else you would be storing A LOT! The actual value depends on what you actually want to see, but please do change it if you increase the number of steps as in the previous item.
3) Run our latest docker container and execute an example.
For example for the kinase-neq-switching example, you would do something like:
```bash
docker run -it --rm --gpus device=0 --mount type=bind,source=$HOME/.OpenEye/,target=/openeye/,readonly --mount type=bind,source=$HOME/repos/perses/examples/,target=/mnt/ -w /mnt/kinase-neq-switching choderalab/perses:0.9.2 python run_example.py
```
Of importance there are the paths to the OpenEye license file (in this example is `$HOME/.OpenEye/`), path to the examples directory in perses (`$HOME/repos/perses/examples/`) and the actual example subdirectory example you want to run (`/mnt/kinase-neq-switching`)
================================================
FILE: docs/Makefile
================================================
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = perses
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
================================================
FILE: docs/_static/README.md
================================================
Blank file to have git ingest this directory
================================================
FILE: docs/analysis.rst
================================================
.. _analysis:
Analysis
********
Analysis methods for perses simulations.
Cache objects
-------------
.. currentmodule:: perses.analysis.analysis
.. autosummary::
:nosignatures:
:toctree: api/generated/
Analysis
================================================
FILE: docs/annihilation.rst
================================================
.. _annihilation:
Alchemical transformations
**************************
Tools for nonequilibrium alchemical transformations
Nonequilibrium switching
------------------------
.. currentmodule:: perses.annihilation.ncmc_switching
.. autosummary::
:nosignatures:
:toctree: api/generated/
NCMCEngine
Relative alchemical transformations
-----------------------------------
.. currentmodule:: perses.annihilation.relative
.. autosummary::
:nosignatures:
:toctree: api/generated/
HybridTopologyFactory
Principle of HybridTopologyFactory
----------------------------------
HybridTopologyFactory is a class that automates the construction of so-called hybrid topologies and systems. In short, this amounts to using an atom map to merge
two initial systems into a new system that contains a union of the former systems' degrees of freedom, along with a ``lambda`` parameter to control the degree to which the hybrid represents the old or new system. The process of creating this system happens in several steps, detailed below. Before proceeding, there are several important caveats:
- Atom maps:
- Atoms whose constraints change between new and old system may not be mapped
- Virtual sites are only permitted if their parameters are identical in the old and new systems
- Systems:
- Only ``HarmonicBondForce``, ``HarmonicAngleForce``, ``PeriodicTorsionForce``, ``NonbondedForce``, and ``MonteCarloBarostat`` are supported. The presence of other forces will raise an exception.
Basic Terminology
^^^^^^^^^^^^^^^^^
Throughout the rest of this document, the following terms will be referenced:
- Hybrid topology: An object that "fuses" two systems based on an atom map, and whose identity is controlled by a set of global parameters called ``lambda``. Mapped atoms are switched from the type in one system to the type in the other; unmapped atoms are switched on or off, depending on which system they belong to.
- Old system: We use this to refer to the endpoint represented by ``lambda=0``.
- New system: We use this to refer to the endpoint represented by ``lambda=1``.
Assignment of Particles to Appropriate Groups
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In order to properly assign parameters to the particles in the hybrid system, the particles are first assigned to one of four groups:
- Environment: These atoms are mapped between the new and old systems, and additionally are not part of a residue that differs between new and old systems.
- Examples: solvent molecules, protein residues outside a changing residue
- Core: These atoms are mapped between the new and old system, but are part of a residue that differs between new and old systems. As such, they may need to change parameters.
- Example: The carbon atoms in a benzene that is being transformed to a chlorobenzene.
- Unique old: These atoms are not in the map, and are present only in the old system
- Example: an extraneous hydrogen atom in a cyclohexane being transformed into a benzene
- Unique new: These atoms are not in the map, and are present only in the new system
- Example: The chlorine atom that appears when a benzene is transformed into a chlorobenzene.
Treatment of different interaction groups
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For each supported force, we have to create at least one custom force, as well as an unmodified force. In general, the interactions are handled as follows:
- Environment-Environment: These interactions are handled by regular unmodified forces, as their parameters never change.
- Environment-{Core, Unique old, Unique new}: These interactions are handled by Custom*Forces. For interactions involving the core atoms, the interaction scales from the parameter in the old system to the parameter in the new system as ``lambda`` is switched from 0 to 1. For interactions involving the unique atoms, the interaction scales from full to zero as ``lambda`` switches from 0 to 1 in unique old atoms, and vice versa for unique new atoms.
- Core-Core interactions: These interactions scale from old system parameters to new system parameters as ``lambda`` is switched from 0 to 1.
- Core-{unique old, unique new} interactions: These interactions scale from the parameters in the old system to the parameters in the new system as ``lambda`` is switched from 0 to 1. This means that unique atoms always maintain intramolecular interactions.
- Unique-old and unique-new interactions: These are disabled.
- intra-Unique atoms: These interactions are always enabled, and as such are handled by an unmodified force.
Force terms
^^^^^^^^^^^
Given the above division of atoms into different groups, the assignment of interactions to different force classes is straightforward.
Bonds
"""""
Bonds are handled with a ``HarmonicBondForce`` and a ``CustomBondForce``.
- ``HarmonicBondForce``: This handles all bond interactions that do not change with lambda.
- ``CustomBondForce``: This handles bond interactions that change with lambda. Bond terms never become zero; they are always on to ensure that molecules do not fly apart
Angles
""""""
Angles are also handled with a ``HarmonicAngleForce`` and a ``CustomAngleForce``
- ``HarmonicAngleForce``: This handles all angle interactions that do not change with lambda.
- ``CustomAngleForce``: This handles angle interactions that change with lambda. Angle terms never become zero; they are always on to ensure overlap.
Torsions
""""""""
Torsions are handled with a ``PeriodicTorsionForce`` and a ``CustomTorsionForce``
- ``PeriodicTorsionForce``: This handles all torsion interactions that do not change with lambda.
- ``CustomTorsionForce``: This handles interactions that change with lambda. Although the torsion potential for a given group of atoms is never set to zero, the force assignments sometimes include zero as an endpoint. This is to handle the case of torsion multiplicities greater than one.
Nonbonded (both sterics and electrostatics)
"""""""""""""""""""""""""""""""""""""""""""
- ``NonbondedForce``: This handles sterics and electrostatics interactions that do not change. All interactions that are involved in custom nonbonded forces are excluded from this force.
- ``CustomBondForce``: This handles the exceptions from the standard ``NonbondedForce`` above.
Nonbonded (Sterics)
"""""""""""""""""""
- ``CustomNonbondedForce``: This handles softcore sterics for interactions that change with lambda. This force uses interaction groups to exclude interactions that do not change with ``lambda`` (and are covered by the ``NonbondedForce`` above). This force supports no cutoff, reaction field, and PME. An important note relates to the dispersion correction; by default, it is not enabled to improve performance. However, it can be enabled as a constructor argument in the HybridTopologyFactory.
Nonbonded (Electrostatics)
""""""""""""""""""""""""""
- ``CustomNonbondedForce``: This is a separate ``CustomNonbondedForce`` that handles electrostatic interactions that change with lambda. This force uses interaction groups to exclude interactions that do not change with ``lambda`` (and are covered by the ``NonbondedForce`` above). This force supports the options nocutoff, reaction field, and PME.
Specific unsupported forces
"""""""""""""""""""""""""""
Any force that is not in one of the above-mentioned classes will cause an exception to be raised. Some important examples of this are:
- Amoeba forces
- GB forces
- CMMotionRemover
Additional Features
^^^^^^^^^^^^^^^^^^^
In addition to creating a hybrid topology dependent on a set of ``lambda_force`` functions, the HybridTopologyFactory can also take advantage of OpenMM's automatic differentiation to provide dU/dlambda. In order to use this
functionality, you must provide alchemical functions to the constructor of HybridTopologyFactory. These functions are described below.
Basic Usage of HybridTopologyFactory
------------------------------------
Basic Construction of Factory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In order to use the HybridTopologyFactory, several objects are necessary:
- :py:class:`perses.rjmc.topology_proposal.TopologyProposal` is a container class which holds so-called new and old systems, topologies, and respective atom maps. It can be created manually using the constructor, or can be obtained through a subcalss of :py:class:`perses.rjmc.topology_proposal.ProposalEngine`.
- You need to supply current positions and new positions for the old and new systems, respectively. It is assumed that the atoms which are mapped will have the same positions. If you only have positions for the old system, you can generate (decent) positions for the new system using :py:class:`perses.rjmc.geometry.FFAllAngleGeometryEngine`. You should minimize the hybrid topology that results after this to avoid clashes, however.
- The dispersion correct is calculated for the sterics force if ``use_dispersion_correction`` is set to ``True``. It is false by default; whether to enable this depends on what sort of calculation you are doing:
- Your calculation requires frequent changes to ``lambda`` parameters, such as nonequilibrium switching: Set the dispersion correction to false.
- Your calculation runs a simulation at a set of constant ``lambda`` values (that don't change during the simulation), such as thermodynamic integration: Set the dispersion correction to True.
- The alchemical functions argument can be supplied to the ``HybridTopologyFactory``, in which case only ``lambda`` will be exposed. Otherwise, each individual energy term will have a ``lambda`` associated with it.
Alchemical functions
^^^^^^^^^^^^^^^^^^^^
The functions argument allows you to specify the mathematical relationship between a main `lambda` value, and each individual `lambda`. Adding the functions here also automatically enables the computation of the derivative of the energy with respect to ``lambda``, useful for various tasks.
Some important notes about specifying the alchemical functions:
- All ``lambda`` values must be specified. More specifically, the dictionary must have the following form:
.. code-block:: python
functions_dictionary = {
'lambda_bonds' : 'f_bond(lambda)'
'lambda_angles' : 'f_angle(lambda)'
'lambda_torsions' : 'f_torsion(lambda)'
'lambda_sterics' : 'f_sterics(lambda)'
'lambda_electrostatics' : 'f_electrostatics(lambda)'
}
where ``f_{energy_name}()`` is an arbitrary function of ``lambda`` compliant with OpenMM Lepton syntax. See the OpenMM documentation for more information on what kinds of functions can be implemented there.
Example script
^^^^^^^^^^^^^^
Below is a very simple example script that constructs a :py:class:`HybridTopologyFactory` object that can transform a benzene into catechol in vacuum.
.. code-block:: python
#import needed functionality
from topology_proposal import SmallMoleculeSetProposalEngine, TopologyProposal
from perses.annihilation.relative import HybridTopologyFactory
import simtk.openmm.app as app
from openmoltools import forcefield_generators
#these are utility functions to rapidly create test systems.
from perses.utils.openeye import createOEMolFromIUPAC, createSystemFromIUPAC
from perses.utils.data import get_data_filename
#We'll generate the systems by IUPAC name
mol_name = "benzene"
ref_mol_name = "catechol"
#create the benzene molecule and system, as well as a molecule of catechol
m, unsolv_old_system, pos_old, top_old = createSystemFromIUPAC(mol_name)
refmol = iupac_to_oemol(ref_mol_name)
#The SmallMoleculeSetProposalEngine class needs smiles strings
initial_smiles = oechem.OEMolToSmiles(m)
final_smiles = oechem.OEMolToSmiles(refmol)
#set up the SystemGenerator
gaff_xml_filename = get_data_filename("data/gaff.xml")
system_generator = SystemGenerator([gaff_filename])
#The GeometryEngine will be useful for generating new positions
geometry_engine = FFAllAngleGeometryEngine()
#Instantiate the proposal engine, which will generate the TopologyProposal.
proposal_engine = SmallMoleculeSetProposalEngine(
[initial_smiles, final_smiles], system_generator, residue_name=mol_name)
#generate a TopologyProposal with the SmallMoleculeSetProposalEngine
topology_proposal = proposal_engine.propose(solvated_system, solvated_topology)
#Generate new positions with the GeometryEngine--note that the second return value (logp) is ignored for this purpose
new_positions, _ = geometry_engine.propose(topology_proposal, solvated_positions, beta)
#instantiate the HybridTopologyFactory
factory = HybridTopologyFactory(topology_proposal, old_positions, new_positions)
#Now you have the objects you need to run a simulation, controlled by the `lambda` parameters.
hybrid_system = factory.hybrid_system
hybrid_topology = factory.hybrid_topology
initial_hybrid_positions = factory.hybrid_positions
================================================
FILE: docs/bias.rst
================================================
.. _bias:
Bias engine
***********
Bias engine for sampling chemical space
.. currentmodule:: perses.bias
.. autosummary::
:nosignatures:
:toctree: api/generated/
BiasEngine
MinimizedPotentialBias
================================================
FILE: docs/changelog.rst
================================================
.. _changelog:
***************
Release history
***************
This section lists features and improvements of note in each release.
The full release history can be viewed `at the GitHub perses releases page <https://github.com/choderalab/perses/releases>`_.
0.10.3 - Release
----------------
Bugfix release.
Enhancements
^^^^^^^^^^^^
* Print perses version on startup by @mikemhenry in https://github.com/choderalab/perses/pull/1176
* Support pymbar 3 & 4 by @mikemhenry in https://github.com/choderalab/perses/pull/1173
* Store initial and final topologies for all phases -- small molecule pipeline by @ijpulidos in https://github.com/choderalab/perses/pull/1210
Documentation
^^^^^^^^^^^^^
* Added MPI example with dipeptide mutation by @ijpulidos in https://github.com/choderalab/perses/pull/1228
* Update comments in ``RESTCapableHybridTopologyFactory`` doc string by @zhang-ivy in https://github.com/choderalab/perses/pull/1189
* Clean examples -- CLI protein-ligand example for Tyk2 by @ijpulidos in https://github.com/choderalab/perses/pull/1223
Bug Fixes
^^^^^^^^^
* Fix spectator support by @ijpulidos in https://github.com/choderalab/perses/pull/1233
* Realtime analysis interval to default to checkpoint interval by @ijpulidos in https://github.com/choderalab/perses/pull/1227
* Correctly set cutoff for ``CustomNonbondedForce`` in ``HybridTopologyFactory`` when using a non-default cutoff distance. by @mikemhenry in
* Backport openfe fixes for context deletion by @mikemhenry in https://github.com/choderalab/perses/pull/1229
Testing/CI/Packaging
^^^^^^^^^^^^^^^^^^^^
* Run CI on new 0.10.x branch by @mikemhenry in https://github.com/choderalab/perses/pull/1212
* Use python executable from env by @mikemhenry in https://github.com/choderalab/perses/pull/1174
* Remove example testing by @mikemhenry in https://github.com/choderalab/perses/pull/1214
* CI miscellaneous fixes by @ijpulidos in https://github.com/choderalab/perses/pull/1217
* Improve docker building by @mikemhenry in https://github.com/choderalab/perses/pull/1200
**Full Changelog**: https://github.com/choderalab/perses/compare/0.10.2...0.10.3
0.10.2 - Release
----------------
Bugfix release.
Enhancements
^^^^^^^^^^^^
* Added support for reading input files (ex yaml, sdf, pdbs) from AWS, GCP, and Azure. See the documentation for [cloudpathlib](https://cloudpathlib.drivendata.org/stable/authentication/) for how to setup authentication. Currently only reading the yaml from S3 is unit tested (ie `perses-cli --yaml s3://perses-testing/template_s3.yaml`), but other cloud providers and input files should work. `AzureBlobPath`, `S3Path` and `GSPath` are supported URI endpoints. Please report any issues on our issue tracker! by @mikemhenry in https://github.com/choderalab/perses/pull/1073
* ``CUDA`` platform was hardcoded in geometry engine, generating performance issues by not clearing openmm contexts correctly. Fixed by defaulting to using the faster ``CPU`` platform (for the geometry engine) and explicitly deleting context variables after they are used. by @ijpulidos in https://github.com/choderalab/perses/pull/1091
* Set aromatic draw style to `OEAromaticStyle_Circle` in atom mapper rendering by @mikemhenry in https://github.com/choderalab/perses/pull/1103
* Ligands with atoms changing constrained status were not being handled by mapping proposal. Atoms in bonds that change constrained/unconstrained to unconstrained/constrained during the transformation are now _demapped_. by @ijpulidos in https://github.com/choderalab/perses/pull/1125
* Now that upstream ``openmmtools`` is storing velocities on checkpoint, the small molecule transformation pipeline does not reassign velocities on resume by default. Instead, the velocities are read from the checkpoint file. by @ijpulidos in https://github.com/choderalab/perses/pull/1133
* CLI workflow for replica exchange now uses the faster ``LangevinMiddleIntegrator`` via the ``LangevinDynamicsMove``. Tests were updated to reflect the changes. by @ijpulidos in https://github.com/choderalab/perses/pull/1138
* Add opencontainers image-spec to `Dockerfile` by @SauravMaheshkar in https://github.com/choderalab/perses/pull/1139
* Updated to support openff-toolkit 0.11, which included API-breaking changes. by @jchodera in https://github.com/choderalab/perses/pull/1128
* Make solute-only trajectory writing optional. This option is controlled by the `atom_selection` option in the yaml file. The syntax uses the MDTraj selection syntax, e.g. `not water` @mikemhenry in https://github.com/choderalab/perses/pull/1185
* Users can now specify solvent model for simulations using the ``solvent_model`` field in the input YAML file. Supported values are 'tip3p', 'spce', 'tip4pew', 'tip5p', and 'swm4ndp' (polarizable) by @ijpulidos in https://github.com/choderalab/perses/pull/1202
Documentation
^^^^^^^^^^^^^
* Document setting `ionic_strength` in `examples/new-cli/template.yaml` by @mikemhenry in https://github.com/choderalab/perses/pull/1104
* Add reproducible version of COVID Moonshot example anyone can run as an example by @jchodera in https://github.com/choderalab/perses/pull/1145
* Speed up RTD env generation by @mikemhenry in https://github.com/choderalab/perses/pull/1105
* Fix documentation string for `ProteinMutationExecutor`, using `False` for `reassign_velocities` parameter. by @ijpulidos in https://github.com/choderalab/perses/pull/1169
* Document how to control the log level in the CLI by @mikemhenry in https://github.com/choderalab/perses/pull/1198
Bug Fixes
^^^^^^^^^
* Fixes bug where if a `:` was in a key, we could not override the argument in our perses-cli. @mikemhenry in https://github.com/choderalab/perses/pull/1062
* Resolves #1157 objects serialized with `utils.data.serialize` now will be compressed with `bzip2` or `gzip` depending on file name (`.gz` and `.bz2`, respectively) by @mikemhenry in https://github.com/choderalab/perses/pull/1163
* Fixes for new openmmtools 0.23.0 by @mikemhenry in https://github.com/choderalab/perses/pull/1203
Testing/CI/Packaging
^^^^^^^^^^^^^^^^^^^^
* add python 3.10 to CI by @mikemhenry in https://github.com/choderalab/perses/pull/1080
* skip broken tests by @mikemhenry in https://github.com/choderalab/perses/pull/1074
* Feat/fix ssl gpu error by @mikemhenry in https://github.com/choderalab/perses/pull/1095
* Previously the keyword argument `save_freq` in `validate_endstate_energies_md` was not functional and the value of `250` steps was hard coded. Now, `save_freq` works and has a default value of `250` steps. by @mikemhenry in https://github.com/choderalab/perses/pull/1101
* fix issue with test asset name by @mikemhenry in https://github.com/choderalab/perses/pull/1102
* Examples and benchmarks template input files now run vacuum, solvent and complex phases in order. by @ijpulidos in https://github.com/choderalab/perses/pull/1122
* Add openmm 8 to testing matrix by @mikemhenry in https://github.com/choderalab/perses/pull/1124
* Fix resume tests to use new CLI (resolves issue #1150) by @mikemhenry in https://github.com/choderalab/perses/pull/1151
* Avoid testing non-examples in CI by @ijpulidos in https://github.com/choderalab/perses/pull/1164
* only run dev with newest python version by @mikemhenry in https://github.com/choderalab/perses/pull/1165
* remove outdated recipe by @mikemhenry in https://github.com/choderalab/perses/pull/1159
* update release process by @mikemhenry in https://github.com/choderalab/perses/pull/1162
* add env caching to CI by @mikemhenry in https://github.com/choderalab/perses/pull/1178
* Skip failing openmm 8 tests by @mikemhenry in https://github.com/choderalab/perses/pull/1186
* Add small molecule repex consistency tests by @zhang-ivy in https://github.com/choderalab/perses/pull/1065
* Fix RESTTopologyFactory test by @zhang-ivy in https://github.com/choderalab/perses/pull/1188
* enable merge queue by @mikemhenry in https://github.com/choderalab/perses/pull/1206
* Using default online analysis interval in GPU repex tests by @ijpulidos in https://github.com/choderalab/perses/pull/1207
New Contributors
^^^^^^^^^^^^^^^^
* @SauravMaheshkar made their first contribution in https://github.com/choderalab/perses/pull/1139
**Full Changelog**: https://github.com/choderalab/perses/compare/0.10.1...0.10.2
0.10.1 - Release
----------------
Bugfix release.
Bugfixes
^^^^^^^^
- Bug when trying to use the new ``RESTCapableHybridTopologyFactory`` in the small molecule pipeline -- fixed by not specifying a protocol, hence allowing the ``HybridCompatibilityMixin`` object to automatically handle it. Issue `#1039 <https://github.com/choderalab/perses/issues/1039>`_ (PR `#1045 <https://github.com/choderalab/perses/pull/1045>`_)
- Bug in ``create_endstates_from_real_systems()`` -- fixed by setting the global parameters for valence forces to the appropriate endstate. Also added tyk2 transformation test. Issue `#1041 <https://github.com/choderalab/perses/issues/1041>`_ (PR `#1050 <https://github.com/choderalab/perses/pull/1050>`_).
- Bug in the ``RESTCapableHybridTopologyFactory`` lifting expression -- fixed by separating the cutoff distance from the lifting distance. (PR `#1046 <https://github.com/choderalab/perses/pull/1046>`_)
- Fix bug in ``RelativeFEPSetup`` that prevents user from controlling the padding when solvating for solvent phase calculations. (PR `#1053 <https://github.com/choderalab/perses/pull/1053>`_)
- Bug in ``test_unsampled_endstate_energies_GPU`` and ``test_RESTCapableHybridTopologyFactory_energies_GPU`` -- fixed by removing unit-less ``rest_radius`` argument and using default instead. (PR `#1057 <https://github.com/choderalab/perses/pull/1057>`_)
Enhancements
^^^^^^^^^^^^
- Add flag ``transform_waters_into_ions_for_charge_changes`` for disabling the introduction of a counterion for charge changing transformations. Issue `#1004 <https://github.com/choderalab/perses/issues/1004>`_ (PR `#1030 <https://github.com/choderalab/perses/pull/1030>`_)
- Perses output yaml file now adds timestamp and ligands names information (for old and new ligands). Issue `#998 <https://github.com/choderalab/perses/issues/998>`_ (PR `#1052 <https://github.com/choderalab/perses/pull/1052>`_).
- Protein mutation repex internal consistency tests to ensure convergence. So far only testing neutral transformations. Issue `#1044 <https://github.com/choderalab/perses/issues/1044>`_ (PR `#1054 <https://github.com/choderalab/perses/pull/1054>`_).
0.10.0 - Release
----------------
New command line interface (CLI), many enhancements for the API (especially the ``PointMutationExecutor``) and improved testing.
Bugfixes
^^^^^^^^
- Bug in geometry engine's ``_determine_extra_torsions``: when ``topology_index_map``, which contains the atom indices involved in a particular torsion, is None -- fixed by not trying to add that torsion when ``topology_index_map`` is ``None``. (`#855 <https://github.com/choderalab/perses/pull/855>`_)
- Bug generated by changes upstream in the ``openmm`` package -- default method for calculating solvent padding changed, which resulted in smaller boxes. Fixed by adding more padding to the simulation box, it is now 1.1 nm. Openmm issue `#3502 <https://github.com/openmm/openmm/issues/3502>`_. Perses issue `#949 <https://github.com/choderalab/perses/issues/949>`_ (`#953 <https://github.com/choderalab/perses/pull/953>`_)
- Fixed energy bookkeeping in test of ``HybridTopologyFactory`` when a ring amino acid is involved in transformation. (`#969 <https://github.com/choderalab/perses/pull/969>`_)
- Avoid changing the global context cache behavior on module imports. Issue `#968 <https://github.com/choderalab/perses/issues/968>`_ (`#977 <https://github.com/choderalab/perses/pull/977>`_).
- Benchmark free energy plots now shift data to experimental mean. (`#981 <https://github.com/choderalab/perses/pull/981>`_)
- Skip introduction of counterion for charge changing mutations in vacuum and fix typo in the phase name in ``test_resume_protein_mutation_no_checkpoint`` (`#991 <https://github.com/choderalab/perses/pull/991>`_).
- Recovered logging capabilities respecting the ``LOGLEVEL`` environment variable. Issue `#1018 <https://github.com/choderalab/perses/issues/1018>`_ (`#1032 <https://github.com/choderalab/perses/pull/1032>`_).
Enhancements
^^^^^^^^^^^^
- Improved continuous integration (CI) performance. (`#961 <https://github.com/choderalab/perses/pull/961>`_)
- ``PointMutationExecutor`` now accepts both solute and solvated PDBs (previously only accepted solute PDBs). (`#967 <https://github.com/choderalab/perses/pull/967>`_)
- Tests and examples are now using ``openff-2.0.0`` force field instead of ``openff-1.0.0``. (`#971 <https://github.com/choderalab/perses/pull/971>`_)
- Use names (instead of indices) for fetching the force components of a system, avoiding issues with force reordering upstream in ``openmm``. Issue `#993 <https://github.com/choderalab/perses/issues/993>`_ (`#976 <https://github.com/choderalab/perses/pull/976>`_ and `#1007 <https://github.com/choderalab/perses/pull/1007>`_)
- Increase stability of simulations by decreasing the default hydrogen mass to 3 amu in the ``PointMutationExecutor``. Issue `#982 <https://github.com/choderalab/perses/issues/982>`_ (`#983 <https://github.com/choderalab/perses/pull/983>`_).
- Improved CI tests on both CPU and GPU. Better handling of temporary directories, closing opened reporter files when tests are finished, and using same environments for CPU and GPU (`#985 <https://github.com/choderalab/perses/pull/985>`_ `#989 <https://github.com/choderalab/perses/pull/989>`_ `#1012 <https://github.com/choderalab/perses/pull/1012>`_)
- Performance increase when retrieving the old or new positions from the hybrid positions. Issue `#1005 <https://github.com/choderalab/perses/issues/1005>`_ (`#1020 <https://github.com/choderalab/perses/pull/1020>`_)
- Use of unique names for force components in ``HybridTopologyFactory`` (`#1022 <https://github.com/choderalab/perses/pull/1022>`_).
- New function ``create_endstates_from_real_systems()`` for creating unsampled endstates for currently supported hybrid topology factories (`#1023 <https://github.com/choderalab/perses/pull/1023>`_).
- Improve the readability and usability of ``PointMutationExecutor`` and updates how parameters are specified for solvation (`#1024 <https://github.com/choderalab/perses/pull/1024>`_).
New features
^^^^^^^^^^^^
- Introduce ``RESTCapableHybridTopologyFactory``. Hybrid factory that allows for REST scaling, alchemical scaling, and 4th dimension softcore. So far, only working for protein mutations (`#848 <https://github.com/choderalab/perses/pull/848>`_ `#992 <https://github.com/choderalab/perses/pull/992>`_).
- New perses command line interface (CLI) ``perses-cli`` using ``click``. Allowing a more friendly interface for users. It tests the running environment, sets the platform for the simulation and allows interactive overriding arbitrary options in the input YAML file. Former ``perses-relative`` CLI entry point is now deprecated (`#972 <https://github.com/choderalab/perses/pull/972>`_ `#1021 <https://github.com/choderalab/perses/pull/1021>`_ `#1027 <https://github.com/choderalab/perses/pull/1027>`_).
- Support for handling charge changes (by transforming a water into a counterion) for both protein mutations and ligands transformations. `#862 <https://github.com/choderalab/perses/issues/862>`_ (`#973 <https://github.com/choderalab/perses/pull/973>`_).
- Hybrid topology factory class name can now be specified using the ``hybrid_topology_factory`` parameter in the input YAML file (`#988 <https://github.com/choderalab/perses/pull/988>`_).
- Introduce ``unsampled_endstates`` boolean option in input YAML file, which enables/disables creation of unsampled endstates with long-range sterics correction. Issue `#1033 <https://github.com/choderalab/perses/issues/1033>`_ (`#1037 <https://github.com/choderalab/perses/pull/1037>`_).
0.9.5 - Release
---------------
Enhancements
---------------
- (PR `#948 <https://github.com/choderalab/perses/pull/948>`_ & PR `#952 <https://github.com/choderalab/perses/pull/952>`_) Add citation file, which should enhance the citation generated by Zenodo.
0.9.4 - Release
---------------
Performance optimizations:
^^^^^^^^^^^^^^^^^^^^^^^^^
- (PR `#938 <https://github.com/choderalab/perses/pull/938>`_) Separate ContextCache objects are now created for propagation and energy computation in replica exchange calculations to avoid periodic cycling behavior.
Bugfixes
^^^^^^^^
- (PR `#938 <https://github.com/choderalab/perses/pull/938>`_) Mixed precision and deterministic forces are used by default.
- (PR `#938 <https://github.com/choderalab/perses/pull/938>`_) Velocities are refreshed from the Maxwell-Boltzmann distribution each iteration to avoid sudden cooling when simulations are resumed.
- (PR `#944 <https://github.com/choderalab/perses/pull/944>`_) Fixes to visualization module.
Enhancements
---------------
- (PR `#909 <https://github.com/choderalab/perses/pull/909>`_) Overhaul of Folding@home setup pipeline
- (PR `#909 <https://github.com/choderalab/perses/pull/909>`_) `use_given_geometries` is now `True` by default
- (PR `#934 <https://github.com/choderalab/perses/pull/934>`_) Preview of new CLI tool perses-cli that takes in a yaml file and creates dummy output. Work in progress. CLI/API still subject to changes.
0.9.3 - Release
---------------
Bugfixes
^^^^^^^^
- (PR `#894 <https://github.com/choderalab/perses/pull/894>`_)
Remove unused argument 'implicitSolvent' from SystemGenerator in tests.
- (PR `#893 <https://github.com/choderalab/perses/pull/893>`_)
Add installation instructions to readme.
- (PR `#892 <https://github.com/choderalab/perses/pull/892>`_)
Allow `generate_dipeptide_top_pos_sys` to accept `demap_CBs`.
- (PR `#878 <https://github.com/choderalab/perses/pull/878>`_)
Fix stochastic failures in RepartitionedHybridTopologyFactory test.
- (PR `#877 <https://github.com/choderalab/perses/pull/877>`_)
Fix naked charge padding (sigmas for hydroxyl hydrogens are changed from 1.0 nm to 0.06 nm).
- (PR `#874 <https://github.com/choderalab/perses/pull/874>`_)
Added readme instructions on how to run perses examples using the docker container with GPUs/CUDA.
- (PR `#866 <https://github.com/choderalab/perses/pull/866>`_)
Fix endstate validation handling in PointMutationExecutor.
- (PR `#860 <https://github.com/choderalab/perses/pull/860>`_)
Simplify `_construct_atom_map` for protein mutations.
- Various CI fixes
* PR `#787 <https://github.com/choderalab/perses/pull/787>`_
* PR `#850 <https://github.com/choderalab/perses/pull/850>`_
* PR `#858 <https://github.com/choderalab/perses/pull/858>`_
* PR `#868 <https://github.com/choderalab/perses/pull/868>`_
* PR `#871 <https://github.com/choderalab/perses/pull/871>`_
* PR `#880 <https://github.com/choderalab/perses/pull/880>`_
* PR `#887 <https://github.com/choderalab/perses/pull/887>`_
* PR `#898 <https://github.com/choderalab/perses/pull/898>`_
New features
^^^^^^^^^^^^
- (PR `#896 <https://github.com/choderalab/perses/pull/896>`_)
Drop support for older OpenMM versions.
We now only support versions >= 7.6.0.
- (PR `#924 <https://github.com/choderalab/perses/pull/924>`_)
Command line utility to automatically run and analyze benchmarks using the data set found in https://github.com/openforcefield/protein-ligand-benchmark/
0.9.2 - Bugfix release
-----------------------
Bugfixes
^^^^^^^^
- (PR `#835 <https://github.com/choderalab/perses/pull/835>`_)
Write out YAML file after all options are parsed and set. Saved as YAML original file name + date + time. Resolves
`#817 <https://github.com/choderalab/perses/issues/817>`_.
- (PR `#840 <https://github.com/choderalab/perses/pull/840>`_)
Minor improvements to point mutation executor. Make sure reverse geometry proposal is directly after forward proposal.
Fixes formatting problem for complex positions.
- (PR `#841 <https://github.com/choderalab/perses/pull/841>`_)
Minor improvements to PolymerProposalEngine.
- (PR `#844 <https://github.com/choderalab/perses/pull/844>`_)
Minimal examples of amino acid (small molecule), protein-ligand and ligand mutations, with automated testing.
- (PR `#849 <https://github.com/choderalab/perses/pull/849>`_)
Use an instance of ContextCache instead of the default global instance.
More info at `#613 (comment) <https://github.com/choderalab/perses/issues/613#issuecomment-899746348>`_.
New features
^^^^^^^^^^^^
- (PR `#708 <https://github.com/choderalab/perses/pull/708>`_)
Create visualization module for generating PyMOL movies.
- (PR `#834 <https://github.com/choderalab/perses/pull/834>`_)
Enable protein mutation transformations involving nonstandard amino acids, specifically: ASH, GLH, HID, HIE, HIP, LYN.
- (PR `#838 <https://github.com/choderalab/perses/pull/838>`_)
Official Docker image hosted on docker hub ``docker pull choderalab/perses:0.9.2``.
Resolves `#832 <https://github.com/choderalab/perses/pull/832>`_.
0.9.1 - Bugfix release
-----------------------
Bugfixes
^^^^^^^^
- (PR `#830 <https://github.com/choderalab/perses/pull/830>`_)
Added limited support for resuming simulations from the CLI.
Assumes simulations are only going to be resumed from the production step and not equilibration step.
To extend the simulation, change ``n_cycles`` to a larger number and re-run the CLI tool.
``LOGLEVEL`` can now be set with an environmental variable when using the CLI tool.
- (PR `#821 <https://github.com/choderalab/perses/pull/821>`_)
Added tests for the resume simulation functionality.
- (PR `#828 <https://github.com/choderalab/perses/pull/828>`_)
Addresses (`issue #815 <https://github.com/choderalab/perses/issues/815>`_) by checking the potential energy of the proposed positions before generating the ``RepartitonedHybridTopologyFactory``.
- (PR `#809 <https://github.com/choderalab/perses/pull/809>`_)
The atom mapping facility was overhauled to address a bug in mapping rings (`#805 <https://github.com/choderalab/perses/issues/805>`_).
Atom mapping is now handled via an ``AtomMapper`` factory that generates an ``AtomMapping`` class that localizes all relevant functionality.
- (PR `#824 <https://github.com/choderalab/perses/pull/824>`_)
The default timestep is now 4 fs (was 1 fs) and the minimum openMM version is now 7.5.0
- (PR `#812 <https://github.com/choderalab/perses/pull/812>`_)
Automatically set package version by ``git tag`` using versioneer
- (PR `#804 <https://github.com/choderalab/perses/pull/804>`_)
Set the default temperature back to 300 K for ``relative_point_mutation_setup.py``.
- (PR `#796 <https://github.com/choderalab/perses/pull/796>`_)
Removed defunct ``atom_map`` argument from FEP constructor.
================================================
FILE: docs/conf.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# perses documentation build configuration file, created by
# sphinx-quickstart on Sun May 14 17:09:48 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.mathjax',
'numpydoc',
'sphinx.ext.doctest',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
#'sphinx.ext.githubpages'
]
autosummary_generate = True
autodoc_default_options = {
"members": True,
"inherited-members": True,
}
# autodoc_mock_imports = [
# "matplotlib",
# "mdtraj",
# "netCDF4",
# "networkx",
# "oechem",
# "openeye",
# "openforcefield",
# "openmmtools",
# "openmoltools",
# "parmed",
# "progressbar",
# "pymbar",
# "scipy",
# "seaborn",
# "simtk",
# "tqdm",
# # "numba", # this must be installed because mocking fails with jit stuff
# # "perses.rjmc.coordinate_numba",
# ]
numpydoc_class_members_toctree = False
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'perses'
copyright = '2016-2017, Chodera lab // MSKCC'
author = 'Chodera lab // MSKCC'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = ''
# The full version, including alpha/beta/rc tags.
release = ''
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
#pygments_style = 'sphinx'
pygments_style = 'paraiso-dark'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- Options for HTML output ----------------------------------------------
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
"logo_name": 'true',
'page_width': 'auto',
'github_button': 'true',
'github_user': 'choderalab',
'github_repo': 'perses',
'github_banner': 'true',
'travis_button': 'false',
'show_powered_by' :'true',
'font_family': 'calibri, helvetica, sans-serif',
'head_font_family': 'cambria, tahoma, serif',
'description' : 'A batteries-included toolkit for the GPU-accelerated OpenMM molecular simulation engine',
'pre_bg': '#41323f', # color used for syntax block
'body_text': "#41323f",
"pink_1": "peachpuff",
}
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'persesdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'perses.tex', 'perses Documentation',
'Chodera lab // MSKCC', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'perses', 'perses Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'perses', 'perses Documentation',
author, 'perses', 'One line description of project.',
'Miscellaneous'),
]
================================================
FILE: docs/environment.yml
================================================
name: perses-docs
channels:
- conda-forge
- defaults
dependencies:
- python
- setuptools
- numpy
- numpydoc
- sphinx <5
- numba
================================================
FILE: docs/examples.rst
================================================
.. _examples:
Examples
********
All examples are located in ``perses/examples``. These are designed to demonstrate the functionality of perses, and are hopefully a good starting point to be adapted to other projects.
.. note:: If anything is unclear or incorrect, please open an Issue_.
..
abl-src-selectivity
Atom Mapping
++++++++++++
This example demonstrates some of the possible exposed options that can be used when generating a hybrid topology. What the **best** hybrid topology is for a simulation is an open research question.
If you go from toluene to phenol, should the methyl carbon be 'mapped' onto the phenol oxygen and therefore be in the core? Or should they be both be unique atoms?
First, the mapping is illustrated with some SMILES molecules of some small aromatic molecules.
PINK shows unique-old atoms and PURPLE shows unique-new. These atoms will be switched off and on respectively across an alchemical protocol. GREEN indicates core atoms that are changing element.
Look at the toluene to nitrobenzene example:
.. image:: images/toluene-nitrobenzene.png
:width: 500
The carbon is mapped onto the nitrogen. How could they be removed from the mapping? adding 'AtomicNumber' to ``atom_expr`` is one option, or 'FormalCharge' would work if you would want a methyl group to map onto a amine group but not a nitro.
It's worth playing around with these options and seeing what works best for your particular project before committing lots of compute.
The next section uses Bace to demonstrate it on a few ligands. A few pairs of ligands are chosen, and the maps using IntType for atoms and RingMember for bonds. IntType is special in perses, as by default, it's used to represent the size of the rings that an atom is in. Try setting atom_type to 0 and see what the maps look like. It's unlikely that a simulation using this map would perform well.
The next section uses two Jnk1 ligands to demonstrate two different sorts of mapping strategy. The first uses 'core'. This returns the map that puts the most atoms in the core - so that the overlap between ligand A and ligand B is maximized. Most cases, this is the best thing to do, however maximizing the overlap might not be the best if the ligands don't overlap in **space**.
.. figure:: images/jnk1-ligands.png
:width: 500
Ligands 0 (green) and 1 (yellow) for Jnk1 shown in 3D space. Notice that the meta substitutions (methyl and ether groups respectively) point in different directions. These may not interconvert through rotations in the active site.
You can see above that the methyl group and the ether group point in different directions, which corresponds to different binding modes in the active site. Now lets look at the 'core' mapping strategy (which is the default). The O and the C are mapped (i.e. green). We can try stop them mapping like before (using AtomicNumber), but they're always going to map coming off carbon 19. This is because having the hydrogen 22 mapped is maximizing the number of atoms in the core.
.. figure:: images/core.png
:width: 500
This is the mapping when the default 'core' strategy is used.
To get the geometry right, we want to have fewer atoms in the core, so try the mapping strategy 'geometry'. This will use the coordinates of the molecule to pick the best map. If they did point the same direction in the active site, it would return the same map as core anyway --- try ligand indices 0 and 6 to see this. Geometry is `only` going to work if the geometry associated with the ligands is meaningful. With these Jnk1 ligands, we have the molecules aligned as they should be in the active site.
.. figure:: images/geometry.png
:width: 500
This is the mapping when the 'geometry' strategy is used. This is `only` useful if the binding mode of the second ligand is known.
The way the 'geometry' strategy works, is by getting the scaffolds of the molecules, and enumerating all the ways that they fit onto each other to enumerate the 'symmetry'. This method of using the scaffolds allows us to spot rotatable aromatic rings or alternative orientations without hydrogens adding to the score making only one orientation preferable.
These symmetry scaffold pairs are then used as restraints to find as many maps as possible --- look at the final two maps --- the whole molecule has been flipped around as the symmetry has identified the pattern where the molecule is inverted around the carbonyl. The ``geometry score`` is the sum of cartesian distances between mapped atoms. The best geometry score (of 9) is for the one that recapitulates the input best. The worst score (~111) where the whole molecule is flipped is very far from the binding pose, but could be an interesting experiment to run if we had no idea of the binding pose for ligand B.
Sampler Example
+++++++++++++++
This folder contains an example setup for a protein-ligand relative free energy calculation for ligands bound to CDK2. The input files in this directory are from the Schrodinger JACS dataset (publication [#]_ and input files [#]_ ), with the protein pdb fixed using PDBFixer.
This example demonstrates how the free energy can be calculated using different sampler methods: REPEX, SAMS and nonequilibrium switching. Notice that the ``fe_type`` in each of these differ.
The ``.yaml`` files in each case contain input parameters for the simulations. Each of these contains a pair of ligand IDs that correspond to the molecule index in the ligand input file ``CDK2_ligands_shifted.sdf``.
.. note:: The ligand input is zero-indexed.
Look at the files and see which parameters are used for each free energy method type. The ``neq_splitting`` is only defined in ``cdk2_nonequilibrium.yaml``, as it's specific to non-equilibrium sampling.
The example can be run by calling ``perses-relative cdk2_sams.yaml``. By default, the included yaml file directs the code to set up and run the complex, solvent and vacuum phase.
The yaml file only sets up a pairwise comparison for two ligands. To run a range of ligands, change the ``ligand_pairs`` in run.py to those of interest. This will then copy the input yaml to make individual yaml files per pair.
To submit the job on a LSF cluster, use ``submit-ligpairs.sh``, to change the jobarray so that it is the same length of the list of ligand pairs.
Use ``bsub < submit-ligpairs.sh`` (if on LSF, or adapt as appropriate).
..
freesolv
..
host-guest
..
mcl1-example
..
neq-switching
..
relay-example
..
rjmc
..
thrombin_fah_generator
.. _Issue: https://github.com/choderalab/perses/issues/new
Python_ is `my favourite
programming language`__.
References
----------
.. [#] `Accurate and Reliable Prediction of Relative Ligand Binding Potency in Prospective Drug Discovery by Way of a Modern Free-Energy Calculation Protocol and Force Field` Lingle Wang et al. JACS 137:2695, 2017.
.. [#] `Input files are here <https://drive.google.com/drive/u/1/folders/0BylmDElgu6QLTnJ2WGMzNXBENkk>`_.
================================================
FILE: docs/index.rst
================================================
.. perses documentation master file, created by
sphinx-quickstart on Sun May 14 17:09:48 2017.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. caution::
This is module is undergoing heavy development. None of the API calls are final.
This software is provided without any guarantees of correctness, you will likely encounter bugs.
If you are interested in this code, please wait for the official release to use it.
In the mean time, to stay informed of development progress you are encouraged to:
* Follow `this feed`_ for updates on releases.
* Check out the `github repository`_ .
.. _this feed: https://github.com/choderalab/perses/releases.atom
.. _github repository: https://github.com/choderalab/perses
PERSES
======
A Python framework for automated small molecule free energy driven design.
``PERSES`` is a Python framework that uses `OpenMM <http://openmm.org>`_ for GPU-accelerated molecular design driven by alchemical free energy calculations.
.. toctree::
:maxdepth: 2
:caption: Contents:
installation
changelog
examples
Background
----------
Perses performs relative free energy calculations using a single topology method. Single topology methods are those where the two 'things' that are being compared are done so by generating a single object whose parameters are perturbed between a representation of thing A to thing B. Perses supports perturbations between small molecules (for relative binding or relative hydration free energy calculations) and protein residues (resistance mutations).
Setting up and running a perses calculations involves three main stages.
Determining the atom-mapping of ligand A onto ligand B to work out the 2D topology of the single-topology alchemical object. Herein, alchemical topologies, systems, geometries etc. will be referred to as *hybrid*. This is handled by a ``ProposalEngine``.
From this 2D hybrid topology, we then generate a 3D hybrid system. We use the input topology and coordinates for ligand A and the system and use RJMC to build in the atoms of ligand B. This is handled by a ``GeometryEngine``.
With the hybrid system and hybrid topology, it's possible to perform free energy calculations. Equilibrium methods such as REPEX and SAMS or non-equilibrium switching can be used. The method in which ligand A and ligand B are perturbed is handled by the ``LambdaProtocol``, and sampled using samplers such as ``HybridSAMSSampler`` and ``HybridRepexSampler``.
Modules
-------
.. toctree::
:maxdepth: 2
annihilation
bias
rjmc
samplers
dispersed
storage
analysis
utils
API Reference
-------------
.. toctree::
:maxdepth: 1
api/generated
Developers
----------
* Patrick B. Grinaway
* Julie M. Behr
* Hannah E. Bruce Macdonald
* Dominic A. Rufa
* Jaime Rodríguez-Guerra
* Ivy Zhang
* Mike Henry
* Iván Pulido
* John D. Chodera
Indices and tables
++++++++++++++++++
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
================================================
FILE: docs/installation.rst
================================================
.. _installation:
Installation
************
Installing via `conda`
======================
The simplest way to install ``perses`` is via the `conda <http://www.continuum.io/blog/conda>`_ package manager.
Packages are provided on the `conda-forge Anaconda Cloud channel <http://anaconda.org/conda-forge>`_ for Linux, OS X, and Win platforms.
The `perses Anaconda Cloud page <https://anaconda.org/conda-forge/perses>`_ has useful instructions and `download statistics <https://anaconda.org/conda-forge/perses/files>`_.
If you are using the `anaconda <https://www.continuum.io/downloads/>`_ scientific Python distribution, you already have the ``conda`` package manager installed.
If not, the quickest way to get started is to install the `miniconda <http://conda.pydata.org/miniconda.html>`_ distribution, a lightweight minimal installation of Anaconda Python.
|
Release build
-------------
You can install the latest stable release build of perses via the ``conda`` package with
.. code-block:: none
$ conda config --add channels conda-forge openeye
$ conda install perses openeye-toolkits
This version is recommended for all users not actively developing new algorithms for alchemical free energy calculations.
.. note:: ``conda`` will automatically dependencies from binary packages automatically, including difficult-to-install packages such as OpenMM, numpy, and scipy. This is really the easiest way to get started.
|
Upgrading your installation
---------------------------
To update an earlier ``conda`` installation of perses to the latest release version, you can use ``conda update``:
.. code-block:: bash
$ conda update perses
|
================================================
FILE: docs/rjmc.rst
================================================
.. _rjmc:
Molecular geometry generation via RJMC
**************************************
Reversible jump Monte Carlo (RJMC) engine for sampling molecular geometries in which atoms are created/destroyed.
Atom mapping
------------
.. currentmodule:: perses.rjmc.atom_mapping
.. autosummary::
:nosignatures:
:toctree: api/generated/
AtomMapping
AtomMapper
Topology proposal engines
-------------------------
.. currentmodule:: perses.rjmc.topology_proposal
.. autosummary::
:nosignatures:
:toctree: api/generated/
TopologyProposal
ProposalEngine
.. SmallMoleculeAtomMapper
.. PremappedSmallMoleculeSetProposalEngine
SmallMoleculeSetProposalEngine
PolymerProposalEngine
PointMutationEngine
PeptideLibraryEngine
.. JRG: This class does not exist anymore?
.. ButaneProposalEngine
.. NaphthaleneProposalEngine
.. PropaneProposalEngine
.. NullProposalEngine
OpenMM System generation utilities
----------------------------------
.. currentmodule:: perses.rjmc.topology_proposal
.. autosummary::
:nosignatures:
:toctree: api/generated/
.. .. This has moved to openforcefields?
.. SystemGenerator
Geometry proposal engines
-------------------------
.. currentmodule:: perses.rjmc.geometry
.. autosummary::
:nosignatures:
:toctree: api/generated/
GeometryEngine
FFAllAngleGeometryEngine
.. JRG: This class does not exist anymore?
.. OmegaGeometryEngine
Geometry utility classes
------------------------
.. currentmodule:: perses.rjmc.geometry
.. autosummary::
:nosignatures:
:toctree: api/generated/
GeometrySystemGenerator
.. JRG: These classes does not exist anymore?
.. BootstrapParticleFilter
.. GeometrySystemGeneratorFast
.. PredAtomTopologyIndex
.. PredHBond
.. .. This one is also dead code in some modules!
.. ProposalOrderTools
================================================
FILE: docs/samplers.rst
================================================
.. _samplers:
Sampler stack
*************
Samplers for driving sampling over conformations or chemical states.
.. currentmodule:: perses.samplers
.. autosummary::
:nosignatures:
:toctree: api/generated/
ExpandedEnsembleSampler
SAMSSampler
MultiTargetDesign
ProtonationStateSampler
================================================
FILE: docs/storage.rst
================================================
.. _storage:
Storage handling
****************
Storange handling driver
.. currentmodule:: perses.storage
.. autosummary::
:nosignatures:
:toctree: api/generated/
NetCDFStorage
================================================
FILE: examples/README.md
================================================
Examples
========
This directory contains examples of the different modules in perses that can are used expanded
ensemble simulations using various methods.
Subdirectories
--------------
The examples are organized in subdirectories as follows. More information on each example in the `README` files inside
each subdirectory.
* [`atom-mapping`](atom-mapping) - Notebooks and script with examples on how to use perses atom mapping capabilities.
* [`barnase-barstar-neq-switching`](barnase-barstar-neq-switching) - FE estimate using NEQ switching in protein:protein barnase-barnase complex.
* [`dipeptide-neq-switching`](dipeptide-neq-switching) - Alanine dipeptide mutation using NEQ switching.
* [`kinase-neq-switching`](kinase-neq-switching) - NTKR1 kinase protein-ligand FE simulation using NEQ cycling
* [`moonshot-mainseries`](moonshot-mainseries) - Scripts used to prepare simulations to run with perses CLI for the COVID Moonshot
* [`protein-ligand-repex`](protein-ligand-repex) - Tyk2 protein-ligand benchmark Replica Exchange simulation examples, using perses CLI.
================================================
FILE: examples/atom-mapping/Atom-mapping.ipynb
================================================
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Experimenting with the `AtomMapper` factory\n",
"\n",
"This notebook illustrates use of the `AtomMapper` factor, which proposes potentially valid atom mappings.\n",
"Note that `perses` has specific additional requirements for atom mappings (such as the inability to turn constrained X-H bonds into unconstrained ones) that may further require de-mapping some atoms after this stage."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Let's take a look at some atom mappings"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# First, create some molecules to work with\n",
"from openff.toolkit.topology import Molecule\n",
"benzene = Molecule.from_smiles('c1ccccc1')\n",
"toluene = Molecule.from_smiles('c1ccccc1C')\n",
"phenol = Molecule.from_smiles('c1ccccc1O')\n",
"catechol = Molecule.from_smiles('c1cccc(O)c1O')\n",
"nitrobenzene = Molecule.from_smiles('C1=CC=C(C=C1)[N+](=O)[O-]')\n",
"cyclohexane = Molecule.from_smiles('C1CCCCC1')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "4d9d7bfa93d84164933c88863521db84",
"version_major": 2,
"version_minor": 0
},
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<rdkit.Chem.rdchem.Mol at 0x7fa370fad450>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Remember that OpenFF molecules can be visualized\n",
"phenol"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<rdkit.Chem.rdchem.Mol at 0x7fa373846b30>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<rdkit.Chem.rdchem.Mol at 0x7fa373846b30>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<rdkit.Chem.rdchem.Mol at 0x7fa373846c70>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<rdkit.Chem.rdchem.Mol at 0x7fa373846ea0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(benzene, toluene, phenol, catechol)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# Create an AtomMapper factory using the default mapping criteria\n",
"from perses.rjmc.atom_mapping import AtomMapper\n",
"atom_mapper = AtomMapper()\n",
"\n",
"# Create an atom mapping for the default criteria\n",
"atom_mapping = atom_mapper.get_best_mapping(phenol, catechol)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"AtomMapping : [H:10][c:3]1[c:2]([c:1]([c:6]([c:5]([c:4]1[H:11])[H:12])[O:7][H:13])[H:8])[H:9] -> [H:10][c:2]1[c:3]([c:4]([c:5]([c:7]([c:1]1[H:9])[O:8][H:14])[O:6][H:13])[H:12])[H:11] : mapped atoms {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10, 10: 11, 12: 13}\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABLAAAAJYCAYAAABy5h8aAAAAAXNSR0IArs4c6QAAAHhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAACQAAAAAQAAAJAAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAABLCgAwAEAAAAAQAAAlgAAAAAXBRVxAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAQABJREFUeAHs3QecFEXax/E/sCASJAoIBkyIAioYwCyKGBE5MetxBtRTX0VFDJhzVoynngHFcAYURVBP0VMMoGJCQQRBJSiSkwIL89bTOMPusjvdMzuz0z3zq/vs7cx0dXf1txqn9ukK1WIuiYQAAggggAACCCCAAAIIIIAAAggggEBIBaqHtFwUCwEEEEAAAQQQQAABBBBAAAEEEEAAAU+AABY3AgIIIIAAAggggAACCCCAAAIIIIBAqAUIYIW6eigcAggggAACCCCAAAIIIIAAAggggAABLO4BBBBAAAEEEEAAAQQQQAABBBBAAIFQCxDACnX1UDgEEEAAAQQQQAABBBBAAAEEEEAAAQJY3AMIIIAAAggggAACCCCAAAIIIIAAAqEWIIAV6uqhcAgggAACCCCAAAIIIIAAAggggAACBLC4BxBAAAEEEEAAAQQQQAABBBBAAAEEQi1AACvU1UPhEEAAAQQQQAABBBBAAAEEEEAAAQQIYHEPIIAAAggggAACCCCAAAIIIIAAAgiEWoAAVqirh8IhgAACCCCAAAIIIIAAAggggAACCBDA4h5AAAEEEEAAAQQQQAABBBBAAAEEEAi1AAGsUFcPhUMAAQQQQAABBBBAAAEEEEAAAQQQIIDFPYAAAggggAACCCCAAAIIIIAAAgggEGoBAlihrh4KhwACCCCAAAIIIIAAAggggAACCCBAAIt7AAEEEEAAAQQQQAABBBBAAAEEEEAg1AIEsEJdPRQOAQQQQAABBBBAAAEEEEAAAQQQQIAAFvcAAggggAACCCCAAAIIIIAAAggggECoBQhghbp6KBwCCCCAAAIIIIAAAggggAACCCCAAAEs7gEEEEAAAQQQQAABBBBAAAEEEEAAgVALEMAKdfVQOAQQQAABBBBAAAEEEEAAAQQQQAABAljcAwgggAACCCCAAAIIIIAAAggggAACoRYggBXq6qFwCCCAAAIIIIAAAggggAACCCCAAAIEsLgHEEAAAQQQQAABBBBAAAEEEEAAAQRCLUAAK9TVQ+EQQAABBBBAAAEEEEAAAQQQQAABBAhgcQ8ggAACCCCAAAIIIIAAAggggAACCIRagABWqKuHwiGAAAIIIIAAAggggAACCCCAAAIIEMDiHkAAAQQQQAABBBBAAAEEEEAAAQQQCLUAAaxQVw+FQwABBBBAAAEEEEAAAQQQQAABBBAggMU9gAACCCCAAAIIIIAAAggggAACCCAQagECWKGuHgqHAAIIIIAAAggggAACCCCAAAIIIEAAi3sAAQQQQAABBBBAAAEEEEAAAQQQQCDUAgSwQl09FA4BBBBAAAEEEEAAAQQQQAABBBBAgAAW9wACCCCAAAIIIIAAAggggAACCCCAQKgFCGCFunooHAIIIIAAAggggAACCCCAAAIIIIAAASzuAQQQQAABBBBAAAEEEEAAAQQQQACBUAsQwAp19VA4BBBAAAEEEEAAAQQQQAABBBBAAAECWNwDCCCAAAIIIIAAAggggAACCCCAAAKhFiCAFerqoXAIIIAAAggggAACCCCAAAIIIIAAAgSwuAcQQAABBBBAAAEEEEAAAQQQQAABBEItQAAr1NVD4RBAAAEEEEAAAQQQQAABBBBAAAEECGBxDyCAAAIIIIAAAggggAACCCCAAAIIhFqAAFaoq4fCIYAAAggggAACCCCAAAIIIIAAAggQwOIeQAABBBBAAAEEEEAAAQQQQAABBBAItQABrFBXD4VDAAEEEEAAAQQQQAABBBBAAAEEECCAxT2AAAIIIIAAAggggAACCCCAAAIIIBBqAQJYoa4eCocAAggggAACCCCAAAIIIIAAAgggQACLewABBBBAAAEEEEAAAQQQQAABBBBAINQCBLBCXT0UDgEEEEAAAQQQQAABBBBAAAEEEECAABb3AAIIIIAAAggggAACCCCAAAIIIIBAqAUIYIW6eigcAggggAACCCCAAAIIIIAAAggggAABLO4BBBBAAAEEEEAAAQQQQAABBBBAAIFQCxDACnX1UDgEEEAAAQQQQAABBBBAAAEEEEAAAQJY3AMIIIAAAggggAACCCCAAAIIIIAAAqEWIIAV6uqhcAgggAACCCCAAAIIIIAAAggggAACBLC4BxBAAAEEEEAAAQQQQAABBBBAAAEEQi1AACvU1UPhEEAAAQQQQAABBBBAAAEEEEAAAQQIYHEPIIAAAggggAACCCCAAAIIIIAAAgiEWoAAVqirh8IhgAACCCCAAAIIIIAAAggggAACCBDA4h5AAAEEEEAAAQQQQAABBBBAAAEEEAi1AAGsUFcPhUMAAQQQQAABBBBAAAEEEEAAAQQQIIDFPYAAAggggAACCCCAAAIIIIAAAgggEGoBAlihrh4KhwACCCCAAAIIIIAAAggggAACCCBAAIt7AAEEEEAAAQQQQAABBBBAAAEEEEAg1AIEsEJdPRQOAQQQQAABBBBAAAEEEEAAAQQQQIAAFvcAAggggAACCCCAAAIIIIAAAggggECoBQhghbp6KBwCCCCAAAIIIIAAAggggAACCCCAAAEs7gEEEEAAAQQQQAABBBBAAAEEEEAAgVALEMAKdfVQOAQQQAABBBBAAAEEEEAAAQQQQAABAljcAwgggAACCCCAAAIIIIAAAggggAACoRYggBXq6qFwCCCAAAIIIIAAAggggAACCCCAAAIEsLgHEEAAAQQQQAABBBBAAAEEEEAAAQRCLUAAK9TVQ+EQQAABBBBAAAEEEEAAAQQQQAABBAhgcQ8ggAACCCCAAAIIIIAAAggggAACCIRagABWqKuHwiGAAAIIIIAAAggggAACCCCAAAIIEMDiHkAAAQQQQAABBBBAAAEEEEAAAQQQCLUAAaxQVw+FQwABBBBAAAEEEEAAAQQQQAABBBAggMU9gAACCCCAAAIIIIAAAggggAACCCAQagECWKGuHgqHAAIIIIAAAggggAACCCCAAAIIIEAAi3sAAQQQQAABBBBAAAEEEEAAAQQQQCDUAgSwQl09FA4BBBBAAAEEEEAAAQQQQAABBBBAgAAW9wACCCCAAAIIIIAAAggggAACCCCAQKgFCGCFunooHAIIIIAAAggggAACCCCAAAIIIIAAASzuAQQQQAABBBBAAAEEEEAAAQQQQACBUAsQwAp19VA4BBBAAAEEEEAAAQQQQAABBBBAAAECWNwDCCCAAAIIIIAAAggggAACCCCAAAKhFiCAFerqoXAIIIAAAggggAACCCCAAAIIIIAAAgSwuAcQQAABBBBAAAEEEEAAAQQQQAABBEItQAAr1NVD4RBAAAEEEEAAAQQQQAABBBBAAAEECGBxDyCAAAIIIIAAAggggAACCCCAAAIIhFqAAFaoq4fCIYAAAggggAACCCCAAAIIIIAAAggQwOIeQAABBBBAAAEEEEAAAQQQQAABBBAItQABrFBXD4VDAAEEEEAAAQQQQAABBBBAAAEEECCAxT2AAAIIIIAAAggggAACCCCAAAIIIBBqAQJYoa4eCocAAggggAACCCCAAAIIIIAAAgggQACLewABBBBAAAEEEEAAAQQQQAABBBBAINQCBLBCXT0UDgEEEEAAAQQQQAABBBBAAAEEEECAABb3AAIIIIAAAggggAACCCCAAAIIIIBAqAUIYIW6eigcAggggAACCCCAAAIIIIAAAggggAABLO4BBBBAAAEEEEAAAQQQQAABBBBAAIFQCxDACnX1UDgEEEAAAQQQQAABBBBAAAEEEEAAAQJY3AMIIIAAAggggAACCCCAAAIIIIAAAqEWIIAV6uqhcCUFYrGYunbtqho1amjo0KElN63zesmSJbr66qu1zz77qGXLlqpTp4623357HXvssfr000/Xyc8HCCCAAAIIIIAAAtEWoK0Y7fqj9AgggICfQJFfBrYjEBaBq666Su+9955XnOLi4gqLNXbsWB1++OH67bffSuX55ptvZD8vvPCCzj//fN1+++2ltvMGAQQQQAABBBBAILoCtBWjW3eUHAEEEAgiQA+sIErkyamABasGDhyo6667zrccCxcu1DHHHJMIXvXo0UPPPPOMRowYoSuvvFJ169bV6tWrdccdd2jIkCG+xyMDAggggAACCCCAQLgFaCuGu34oHQIIIJApAXpgZUqS42RF4IsvvtApp5yiL7/8MtDxH3roIU2bNs3L279/f912222J/Q4++GD16tVLXbp00fLly3XZZZfpxBNPTGznBQIIIIAAAggggEC0BGgrRqu+KC0CCCBQGQF6YFVGj32zKnDjjTdq1113TQSvatWq5Xu+//3vf16eevXq6dprr10n/4477qjjjjvO+/yXX37R77//vk4ePkAAAQQQQAABBBAIvwBtxfDXESVEAAEEMilAACuTmhwrowL/+c9/FJ/r6txzz9Wrr77qe/z1119fbdu2VefOnWWvy0stWrRIfDxr1qzEa14ggAACCCCAAAIIREeAtmJ06oqSIoAAApkQYAhhJhQ5RlYEqlWr5k3GfsUVV2jnnXdWvHdVspO9+OKLyTZ720aPHu39th5dFuwiIYAAAggggAACCERPgLZi9OqMEiOAAAKVESCAVRk99s2qwKhRo9S4ceOMnsMmc48HsCwoFmRYYkYLwMEQQAABBBBAAAEEMiJAWzEjjBwEAQQQiIwAQwgjU1WFV9BMB68mTZqkPn36eJA1atTwViIsPFWuGAEEEEAAAQQQyA8B2or5UY9cBQIIIBBUgABWUCnyRVrgp59+Uvfu3TVnzhzvOi644AJvNcJIXxSFRwABBBBAAAEEEMiIAG3FjDByEAQQQCCrAgSwssrLwcMgMG7cOC9YZQ0TS0ceeaRs1RoSAggggAACCCCAAAK0FbkHEEAAgWgIEMCKRj1RyjQFRo4cqX322Ue//vqrd4Tjjz9ezz33nIqKmP4tTVJ2QwABBBBAAAEE8kaAtmLeVCUXggACBSBAAKsAKrlQL/Hhhx9Wjx49tGTJEo/g4osv1pAhQwheFeoNwXUjgAACCCCAAAIlBGgrlsDgJQIIIBABAbqhRKCSKGLqAtddd52uvPJKb0ebsP2+++7TmWeemfKBJkyYoOHDhyf2O+qoo9S6devEe78XxcXFGjRokFavXu1l7dChgw466CC/3diOAAIIIIAAAgggkEUB2opZxOXQCCCAQJYECGBlCZbD5k7g7rvvTgSv6tWrpxdeeCHtoNEHH3ygAQMGJC5myy23TCmAtXTpUvXv3z+x/zHHHJN2WRIH4QUCCCCAAAIIIIBA2gK0FdOmY0cEEEAgpwIEsHLKz8kzLfDDDz/okksu8Q5bt25dvf322+rcuXOmT8PxEEAAAQQQQAABBCIoQFsxgpVGkRFAAIG/BAhgcSvklcA555yj5cuXe9e0+eab64033vB+KrrI0047Ta1atapoM58jgAACCCCAAAII5JEAbcU8qkwuBQEECk6AAFbBVXn+XvDEiRP11ltvJS5w/Pjxsp9kab/99iOAlQyIbQgggAACCCCAQJ4I0FbMk4rkMhBAoGAFWIWwYKs+ehdevfra29UmZi+bJk+eXPYj3/flHcd3JzIggAACCCCAAAIIhE6AtmLoqoQCIYAAAhkVoAdWRjk5WDYF9tprL8VisQpPcdhhhyXdXuGObEAAAQQQQAABBBCIvABtxchXIReAAAIIJBVY26UlaTY2IoAAAggggAACCCCAAAIIIIAAAgggkBsBAli5ceesCCCAAAIIIIAAAggggAACCCCAAAIBBQhgBYQiGwIIIIAAAggggAACCCCAAAIIIIBAbgSYAys37pw1ogJTpkzRt99+G7j0CxYsCJyXjAgggAACCCCAAALRFqCtGO36o/QIIBBuAQJY4a4fShcygQEDBsh+SAgggAACCCCAAAIIlBWgrVhWhPcIIIBA5gQYQpg5S46EAAIIIIAAAggggAACCCCAAAIIIJAFAQJYWUDlkAgggAACCCCAAAIIIIAAAggggAACmRNgCGHmLDlSAQjcdNNNOuiggwJfqc2B1bVr18D5CzFj3759lcpcYaeddpoOPPDAQqTimhFAAAEEEEAg5AK0FTNfQbQVM2/KERGIqgABrKjWHOXOiUCbNm204447Bj73woULA+ct1IyvvPKK5syZE/jy99prLwJYgbXIiAACCCCAAAJVKUBbMfPatBUzb8oREYiqAAGsqNYc5UYgTwTat2+fNIC1cuVKff/994mr3WqrrRKveYEAAggggAACCCCQ3wK0FfO7frk6BFIRIICVihZ5EUAg4wLvvvtu0mNeeOGFiQDWBRdcoEMOOSRpfjYigAACCCCAAAII5I8AbcX8qUuuBIHKCjCJe2UF2R8BBLImYF3G77zzTu/4++67r2699dasnYsDI4AAAggggAACCERLgLZitOqL0iJQWQECWJUVZH8EEMiKwOLFi3XWWWd5x65du7YeeeQR1ahRIyvn4qAIIIAAAggggAAC0RKgrRit+qK0CGRCgABWJhQ5BgIIZFzg6quv1qxZs7zjDhw4UMx9lXFiDogAAggggAACCERWgLZiZKuOgiOQtgABrLTp2BGB7AgsWrRIq1evzs7BI3LUqVOn6p577vFK27p1aw0YMCAiJaeYCCCAAAIIIIBAdgVsletYLJbdk4T86LQVQ15BFA+BLAkQwMoSLIdFIFWBL774Qu3atVODBg3UvHlz3XLLLVq+fHmqh8mL/P/+979VXFzsXcs///lP1apVKy+ui4tAAAEEEEAAAQTSFfjkk0+0zTbbqGHDhtpoo4101113yVZrLsREW7EQa51rRkAigMVdgEAIBKzX1cEHH6zvvvvOK82cOXN0ySWXeAEtm5yykJIFrh5//HHvkm3uq1NPPbWQLp9rRQABBBBAAAEE1hGwtuGhhx6qSZMmedt+++032erMHTp00IgRI9bJn88f0FbM59rl2hBILkAAK7kPWxGoEoFRo0bJGiJl05QpU9SrVy9169ZN48ePL7s5L9+//vrribmvjj32WDVp0iQvr5OLQgABBBBAAAEEggq8+eabmjdv3jrZv//+ey+wdcghh8heF0KirVgItcw1IlC+AAGs8l34FAFPoGbNmqUkUh3KVr16ddlPPJU9Xvzz9dZbL/6y3N/vvPOOdtxxR51zzjmaO3duuXny5UNbbTCezj777PhLfiOAAAIIIIAAAqETKNu2y1Zb0XqlJ0sjR470emNZr6wFCxYkyxr5bbQVI1+FXAACaQtUcxMAFvYMgGnTsSMCmROwua522GGHQE/OGjVqpGuuuUY2N1RRUVHmChGCI/3yyy+ySdttEvtdd91VY8aMCUGpKAICCCCAAAIIIJBbgaVLl6p9+/aaNm2ab0GaNm2q66+/Xn379i31INV3xwhkoK0YgUqiiAhkUWBt15AsnoRDI4BAcgHrgfX++++re/fuyTO6rfPnz9e5557rBbzeeust3/xRyvDss88mVmA866yzolR0yooAAggggAACCGRNoG7duho9erT23Xdf33PYfFlnnnmmOnXqpPfee883f5Qy0FaMUm1RVgQyL0AAK/OmHBGBtASaNWsmm99g2LBh2mqrrXyPYRO+H3jggerZs6cmT57smz8KGaxhFk8HHHBA/CW/EUAAAQQQQACBghdo1aqV3n33Xb3wwgtej3U/kK+++kpdu3bVUUcdFajnlt/xwrCdtmIYaoEyIJA7AYYQ5s6eMyNQocCKFSt0991364YbbpCtUOiXbL6F8847T5dffrk22GADv+yh3d68eXPNnj1bNkyyvIlKQ1twCoYAAggggAACCFShwJ9//qnbb79dN998s2x4oV+yObQuvPBCXXrppbLeXFFNtBWjWnOUG4HMCNADKzOOHAWBjApYQGrAgAHeUsmnnHKK7/wFFvC67bbb1KZNGz322GOJYXgZLVSWDzZr1iwveGWnsTkeSAgggAACCCCAAALlC1hAyh5c2sqDJ554oqpVq1Z+xr8+tYCXPRi1tuKQIUMUxWmQaSsmrWI2IlAQAgSwCqKaucioCthTpkcffVRjx47VHnvs4XsZv/32m0499VRvAvSSXax9dwxBhpkzZyZK0a5du8RrXiCAAAIIIIAAAgiUL2DDCp966il99NFHXvuv/FxrP7X21kknnaTdd9/da1+u3RL+V7QVw19HlBCBbAsQwMq2MMdHIAMCO+20kzdx5zPPPKNNNtnE94iff/659tprLx133HGy1VqikEoOGaQHVhRqjDIigAACCCCAQFgEunTpok8++URPPPGENtpoI99iWV7bp0+fPrKeTVFItBWjUEuUEYHsCjAHVnZ9OToCGRdYtmyZbr31Vu/njz/+8D3++uuvr8suu0wDBw707V7uezAyIIAAAggggAACCIRaYMmSJbrxxht15513avny5b5lrVevnq666ir179/fNy8ZEEAAgVwKEMDKpT7nRqASAtazyubJeu655wId5fTTT9dDDz0UKC+ZEEAAAQQQQAABBKItMHXqVC8oNXTo0EAX0q9fP911112B8pIJAQQQyIUAAaxcqHNOBDIoYHNd2QqE48aNS3rU6tWr69dff9WGG26YNF/JjStXrtQHH3ygESNGyJZithUC586d660S2Lp1a28J59122029e/eWTTxPQgABBBBAAAEEEAiXwLvvvuu1Fb/55pukBSsqKvJWga5fv37SfCU30lYsqcFrBBDItgABrGwLc3wEqkBg9erVevzxx71hgjaRe0Vp0qRJ2nrrrSvanPh81apVGjx4sK688krNmDEj8XlFL5o1a6a+ffvKntw1bdq0omx8jgACCCCAAAIIIJADAWvbPfzww17bbs6cORWWYPr06bKJ4f0SbUU/IbYjgEA2BAhgZUOVYyKQI4FFixbp+uuv16BBg7RixYpSpdhmm2303XffyXpiJUvWqDniiCP04YcfJstW7rbNNttML7/8sjp27Fjudj5EAAEEEEAAAQQQyJ3A/Pnzdc011+j+++9XcXFxqYLssMMO+vLLL0t9Vt4b2orlqfAZAghUhQABrKpQ5hwIVLHA5MmTvTkPhg0b5p15yy231Ouvvy4LYiVL06ZNU7du3TRlypRS2dZbbz21a9dOO+64o/d76dKlXh47ZtmneHXq1NGTTz6pI488stQxeIMAAggggAACCCAQDoEJEybowgsv1MiRI70CWRvRXm+++eZJC0hbMSkPGxFAIMsCBLCyDMzhEcilgA3/W7hwodq2bevb88pWqdljjz30+eeflypyjx499OCDD5bbndxWQXzqqae8VQ5tbqx4spUPv/jiC9+AWTw/vxFAAAEEEEAAAQSqXsAWBbJVC62tWK1ataQFoK2Y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
gitextract_2hkw0qsl/ ├── .codecov.yml ├── .gitattributes ├── .github/ │ ├── pull_request_template.md │ └── workflows/ │ ├── CI.yaml │ ├── docker.yaml │ ├── rc-check.yaml │ ├── rc-test.yaml │ └── self-hosted-gpu-test.yml ├── .gitignore ├── CITATION.cff ├── LICENSE ├── MANIFEST.in ├── README.md ├── basesetup.py ├── benchmarks/ │ ├── LSF-job-template.sh │ ├── README.md │ ├── benchmark_analysis.py │ ├── run_benchmarks.py │ └── template.yaml ├── devtools/ │ ├── README.md │ ├── conda-envs/ │ │ └── test_env.yaml │ ├── scripts/ │ │ └── initialize_conda.sh │ └── test.smi ├── docker/ │ ├── Dockerfile │ ├── Dockerfile-add-license │ └── README.md ├── docs/ │ ├── Makefile │ ├── _static/ │ │ └── README.md │ ├── analysis.rst │ ├── annihilation.rst │ ├── bias.rst │ ├── changelog.rst │ ├── conf.py │ ├── environment.yml │ ├── examples.rst │ ├── index.rst │ ├── installation.rst │ ├── rjmc.rst │ ├── samplers.rst │ └── storage.rst ├── examples/ │ ├── README.md │ ├── atom-mapping/ │ │ └── Atom-mapping.ipynb │ ├── barnase-barstar-neq-switching/ │ │ ├── README.md │ │ └── run_example.py │ ├── dipeptide-mutation-repex-rest/ │ │ ├── README.md │ │ ├── configfile │ │ ├── generate_htfs.py │ │ ├── hostfile │ │ └── run_repex.py │ ├── dipeptide-neq-switching/ │ │ ├── README.md │ │ └── run_example.py │ ├── kinase-neq-switching/ │ │ ├── README.md │ │ └── run_example.py │ ├── moonshot-mainseries/ │ │ ├── 00-prep-receptor.py │ │ ├── 01-simulate-receptors.py │ │ ├── 02-generate-poses-posit.py │ │ ├── 02-generate-poses.py │ │ ├── 03-list-absent-molecules.py │ │ ├── README.md │ │ ├── molecules/ │ │ │ ├── CDD CSV Export.csv │ │ │ ├── filter-cdd-export.py │ │ │ ├── mainseries.csv │ │ │ ├── step1.csv │ │ │ ├── step2.csv │ │ │ ├── step3.csv │ │ │ └── step4.csv │ │ ├── perses/ │ │ │ ├── analyze-benchmark-pKa.py │ │ │ ├── extract-trajectories.py │ │ │ ├── run-perses.py │ │ │ ├── submit-all.sh │ │ │ └── template.yaml │ │ └── setup.yaml │ └── protein-ligand-repex/ │ └── cli/ │ ├── README.md │ ├── protein-ligand.yaml │ ├── scripts_utils/ │ │ ├── cleanup.sh │ │ ├── run_star_map.sh │ │ ├── submit-dense-map.sh │ │ └── submit-star-map-serial.sh │ ├── tyk2_ligands.sdf │ └── tyk2_protein.pdb ├── notebooks/ │ ├── Analyze_results.ipynb │ ├── Harmonic oscillators example.ipynb │ ├── README.md │ └── plotting_tools.py ├── notes/ │ ├── README.md │ ├── chodera-research.bib │ ├── manuscript.tex │ └── prsty.bst ├── perses/ │ ├── README.md │ ├── __init__.py │ ├── _version.py │ ├── analysis/ │ │ ├── __init__.py │ │ ├── analyse_sams_convergence.py │ │ ├── analysis.py │ │ ├── analyze-profile.py │ │ ├── cycles.py │ │ ├── extract_trajectory.py │ │ ├── fah_analysis.py │ │ ├── generate-protonated-termini.py │ │ ├── load_simulations.py │ │ ├── resample.py │ │ ├── utils.py │ │ └── visualization.py │ ├── annihilation/ │ │ ├── __init__.py │ │ ├── lambda_protocol.py │ │ ├── ncmc_switching.py │ │ ├── relative.py │ │ └── rest.py │ ├── app/ │ │ ├── __init__.py │ │ ├── cli.py │ │ ├── fah_generator.py │ │ ├── relative_hydration.py │ │ ├── relative_point_mutation_setup.py │ │ ├── relative_setup.py │ │ └── setup_relative_calculation.py │ ├── bias/ │ │ ├── __init__.py │ │ └── bias_engine.py │ ├── data/ │ │ ├── 181L.pdb │ │ ├── 1sb0.pdb │ │ ├── 8mer-example/ │ │ │ └── 4zuh_peptide_capped.pdb │ │ ├── L99A-binders.txt │ │ ├── L99A-non-binders.txt │ │ ├── T4-inhibitors.xml │ │ ├── Tyk2_ligands_example/ │ │ │ ├── Tyk2_ligands_shifted.sdf │ │ │ ├── Tyk2_protein.pdb │ │ │ └── tyk2_0_3.yaml │ │ ├── abl-imatinib/ │ │ │ ├── README.md │ │ │ ├── complex.pdb │ │ │ ├── inhibitor.pdb │ │ │ └── receptor.pdb │ │ ├── abl-src/ │ │ │ ├── abl-imatinib.pdb │ │ │ └── src-imatinib.pdb │ │ ├── ala_vacuum.pdb │ │ ├── amber99sbildn-valence-only.xml │ │ ├── amino_acid_templates/ │ │ │ ├── ALA.pdb │ │ │ ├── ARG.pdb │ │ │ ├── ASH.pdb │ │ │ ├── ASN.pdb │ │ │ ├── ASP.pdb │ │ │ ├── CYS.pdb │ │ │ ├── GLH.pdb │ │ │ ├── GLN.pdb │ │ │ ├── GLU.pdb │ │ │ ├── GLY.pdb │ │ │ ├── HID.pdb │ │ │ ├── HIE.pdb │ │ │ ├── HIP.pdb │ │ │ ├── HIS.pdb │ │ │ ├── ILE.pdb │ │ │ ├── LEU.pdb │ │ │ ├── LYN.pdb │ │ │ ├── LYS.pdb │ │ │ ├── MET.pdb │ │ │ ├── PHE.pdb │ │ │ ├── PRO.pdb │ │ │ ├── SER.pdb │ │ │ ├── THR.pdb │ │ │ ├── TRP.pdb │ │ │ ├── TYR.pdb │ │ │ └── VAL.pdb │ │ ├── arg_solvated.cif │ │ ├── bace-example/ │ │ │ ├── Bace_ligands_shifted.sdf │ │ │ ├── Bace_protein.pdb │ │ │ ├── TLA.sdf │ │ │ └── bace_setup.yaml │ │ ├── barstar-mutation/ │ │ │ ├── 1brs_barnase_renumbered.pdb │ │ │ ├── 1brs_barstar_renumbered.pdb │ │ │ ├── mmc2_barnase.pdb │ │ │ ├── mmc2_barstar.pdb │ │ │ └── mutant.yaml │ │ ├── cdk2-example/ │ │ │ ├── CDK2_fixed_nohet.pdb │ │ │ ├── CDK2_ligands.sdf │ │ │ ├── CDK2_ligands_shifted.sdf │ │ │ ├── CDK2_protein.pdb │ │ │ ├── README.md │ │ │ ├── cdk2-cache.json │ │ │ ├── cdk2_setup_neq.yaml │ │ │ └── cdk2_setup_repex.yaml │ │ ├── clinical-kinase-inhibitors.csv │ │ ├── constant-pH/ │ │ │ ├── abl-imatinib/ │ │ │ │ ├── Imatinib-epik-charged.ffxml │ │ │ │ ├── Imatinib-epik-charged.mol2 │ │ │ │ ├── Imatinib-state-penalties.out │ │ │ │ ├── README.md │ │ │ │ ├── complex.pdb │ │ │ │ ├── generate-ligand-ffxml.py │ │ │ │ ├── inhibitor.pdb │ │ │ │ └── receptor.pdb │ │ │ └── imidazole/ │ │ │ ├── README.md │ │ │ ├── convert.py │ │ │ ├── generate-protomers-from-smiles.py │ │ │ ├── imidazole/ │ │ │ │ ├── imidazole-epik-charged.mol2 │ │ │ │ ├── imidazole-epik-charged.pdb │ │ │ │ ├── imidazole-epik.mae │ │ │ │ ├── imidazole-epik.mol2 │ │ │ │ ├── imidazole-epik.sdf │ │ │ │ ├── imidazole-input.mol2 │ │ │ │ └── imidazole-state-penalties.out │ │ │ └── imidazole.pdb │ │ ├── constrained-to-unconstrained/ │ │ │ └── ligands_constraint_test.sdf │ │ ├── gaff-valence-only.xml │ │ ├── gaff.xml │ │ ├── gaff2.xml │ │ ├── generate_gaff_xml.py │ │ ├── given-geometries/ │ │ │ ├── README.md │ │ │ ├── ligands.sdf │ │ │ └── receptor.pdb │ │ ├── host-guest/ │ │ │ ├── a1.sybyl.mol2 │ │ │ ├── a2.sybyl.mol2 │ │ │ ├── cache.json │ │ │ └── cb7.sybyl.mol2 │ │ ├── kinase-inhibitors.xml │ │ ├── kinase-mutation/ │ │ │ ├── NTRK1.pdb │ │ │ └── entrectinib.sdf │ │ ├── lys_solvated.cif │ │ ├── protein.ff14SB.protonated-termini.xml │ │ ├── protein.ff14SB.xml │ │ ├── schrodinger-jacs-datasets/ │ │ │ ├── Bace_ligands.sdf │ │ │ ├── CDK2_ligands.sdf │ │ │ ├── Jnk1_ligands.sdf │ │ │ ├── MCL1_ligands.sdf │ │ │ ├── PTP1B_ligands.sdf │ │ │ ├── README.md │ │ │ ├── Thrombin_ligands.sdf │ │ │ ├── Tyk2_ligands.sdf │ │ │ └── p38_ligands.sdf │ │ ├── test.smi │ │ ├── thr_vacuum.pdb │ │ └── visualization/ │ │ ├── protein-mutation/ │ │ │ ├── new.dcd │ │ │ ├── new.pdb │ │ │ ├── old.dcd │ │ │ └── old.pdb │ │ └── small-molecule/ │ │ ├── new.dcd │ │ ├── new.pdb │ │ ├── old.dcd │ │ └── old.pdb │ ├── dispersed/ │ │ ├── __init__.py │ │ ├── feptasks.py │ │ ├── parallel.py │ │ ├── smc.py │ │ └── utils.py │ ├── rjmc/ │ │ ├── __init__.py │ │ ├── atom_mapping.py │ │ ├── coordinate_numba.py │ │ ├── coordinate_tools.py │ │ ├── geometry.py │ │ └── topology_proposal.py │ ├── samplers/ │ │ ├── __init__.py │ │ ├── multistate.py │ │ ├── samplers.py │ │ └── thermodynamics.py │ ├── storage/ │ │ ├── __init__.py │ │ ├── movie.py │ │ └── storage.py │ ├── tests/ │ │ ├── __init__.py │ │ ├── benchmark.py │ │ ├── conftest.py │ │ ├── test_GPU.py │ │ ├── test_analysis.py │ │ ├── test_atom_mapping.py │ │ ├── test_cli.py │ │ ├── test_coordinate_numba.py │ │ ├── test_fah.py │ │ ├── test_geometry_engine.py │ │ ├── test_lambda_protocol.py │ │ ├── test_ncmc_integrator.py │ │ ├── test_parallel.py │ │ ├── test_relative.py │ │ ├── test_relative_point_mutation_setup.py │ │ ├── test_relative_setup.py │ │ ├── test_repex.py │ │ ├── test_rest.py │ │ ├── test_resume.py │ │ ├── test_samplers.py │ │ ├── test_smc.py │ │ ├── test_storage.py │ │ ├── test_topology_proposal.py │ │ ├── test_utils.py │ │ ├── test_visualization.py │ │ ├── testsystems.py │ │ └── utils.py │ └── utils/ │ ├── __init__.py │ ├── charge_changing.py │ ├── data.py │ ├── openeye.py │ ├── smallmolecules.py │ └── url_utils.py ├── readthedocs.yml ├── setup.cfg ├── setup.py ├── spec-file.txt └── versioneer.py
SYMBOL INDEX (1088 symbols across 80 files)
FILE: basesetup.py
function find_packages (line 17) | def find_packages():
function check_dependencies (line 32) | def check_dependencies(dependencies):
class CompilerDetection (line 67) | class CompilerDetection(object):
method __init__ (line 78) | def __init__(self, disable_openmp):
method _print_compiler_version (line 120) | def _print_compiler_version(self, cc):
method hasfunction (line 132) | def hasfunction(self, funcname, include=None, libraries=None, extra_po...
method _print_support_start (line 190) | def _print_support_start(self, feature):
method _print_support_end (line 193) | def _print_support_end(self, feature, status):
method _detect_openmp (line 199) | def _detect_openmp(self):
method _detect_sse3 (line 209) | def _detect_sse3(self):
method _detect_sse41 (line 218) | def _detect_sse41(self):
function git_version (line 231) | def git_version():
function write_version_py (line 258) | def write_version_py(VERSION, ISRELEASED, filename='MDTraj/version.py'):
class StaticLibrary (line 291) | class StaticLibrary(Extension):
method __init__ (line 292) | def __init__(self, *args, **kwargs):
class build_ext (line 297) | class build_ext(_build_ext):
method build_extension (line 299) | def build_extension(self, ext):
method build_static_extension (line 305) | def build_static_extension(self, ext):
FILE: benchmarks/benchmark_analysis.py
function get_simdir_list (line 30) | def get_simdir_list(base_dir='.', is_reversed=False):
function get_simulations_data (line 58) | def get_simulations_data(simulation_dirs):
function to_arsenic_csv (line 72) | def to_arsenic_csv(experimental_data: dict, simulation_data: list, out_c...
FILE: benchmarks/run_benchmarks.py
function concatenate_files (line 33) | def concatenate_files(input_files, output_file):
function run_relative_perturbation (line 44) | def run_relative_perturbation(lig_a_idx, lig_b_idx, reverse=False, tidy=...
FILE: examples/moonshot-mainseries/00-prep-receptor.py
function read_pdb_file (line 19) | def read_pdb_file(pdb_file):
function prepare_receptor (line 37) | def prepare_receptor(complex_pdb_filename, output_basepath, assembly_sta...
function prepare_receptor_wrapper (line 394) | def prepare_receptor_wrapper(complex_pdb_file):
FILE: examples/moonshot-mainseries/02-generate-poses-posit.py
function GetFragments (line 12) | def GetFragments(mol, minbonds, maxbonds):
function GetCommonFragments (line 30) | def GetCommonFragments(mollist, frags,
function GetCoreFragment (line 57) | def GetCoreFragment(refmol, mols,
function GetFragmentScore (line 81) | def GetFragmentScore(mol):
function expand_stereochemistry_star (line 89) | def expand_stereochemistry_star(mol):
function expand_stereochemistry (line 113) | def expand_stereochemistry(mols):
function expand_stereochemistry_serial (line 143) | def expand_stereochemistry_serial(mols):
function expand_protonation_states_oemols (line 167) | def expand_protonation_states_oemols(mols):
class BumpCheck (line 215) | class BumpCheck:
method __init__ (line 216) | def __init__(self, prot_mol, cutoff=2.0):
method count (line 220) | def count(self, lig_mol):
function mmff_energy (line 227) | def mmff_energy(mol):
function generate_restricted_conformers (line 244) | def generate_restricted_conformers(receptor, refmol, mol, core_smarts=No...
function has_ic50 (line 386) | def has_ic50(mol):
function get_series (line 403) | def get_series(mol):
function generate_restricted_conformers_star (line 477) | def generate_restricted_conformers_star(args):
function generate_restricted_conformers_best (line 489) | def generate_restricted_conformers_best(args):
function generate_poses (line 558) | def generate_poses(receptor, refmol, target_molecules, output_filename, ...
function filter_by_series (line 622) | def filter_by_series(mols, filter_series='3-aminopyridine-like'):
function filter_by_IC50s (line 640) | def filter_by_IC50s(mols):
function load_molecules (line 648) | def load_molecules(filename, append_warts=False):
function load_fragment (line 688) | def load_fragment(fragid, protonation_state, title=None):
function prepend_fragment_molecules (line 725) | def prepend_fragment_molecules(mols, fragments):
function write_molecules (line 747) | def write_molecules(mols, filename):
function read_design_unit (line 762) | def read_design_unit(fragid, assembly_state, protonation_state):
FILE: examples/moonshot-mainseries/02-generate-poses.py
function GetFragments (line 12) | def GetFragments(mol, minbonds, maxbonds):
function GetCommonFragments (line 30) | def GetCommonFragments(mollist, frags,
function GetCoreFragment (line 57) | def GetCoreFragment(refmol, mols,
function GetFragmentScore (line 81) | def GetFragmentScore(mol):
function expand_stereochemistry_star (line 89) | def expand_stereochemistry_star(mol):
function expand_stereochemistry (line 113) | def expand_stereochemistry(mols):
function expand_stereochemistry_serial (line 143) | def expand_stereochemistry_serial(mols):
function expand_protonation_states_oemols (line 167) | def expand_protonation_states_oemols(mols):
class BumpCheck (line 215) | class BumpCheck:
method __init__ (line 216) | def __init__(self, prot_mol, cutoff=2.0):
method count (line 220) | def count(self, lig_mol):
function mmff_energy (line 227) | def mmff_energy(mol):
function generate_restricted_conformers (line 244) | def generate_restricted_conformers(receptor, refmol, mol, core_smarts=No...
function has_ic50 (line 460) | def has_ic50(mol):
function get_series (line 477) | def get_series(mol):
function generate_restricted_conformers_star (line 554) | def generate_restricted_conformers_star(args):
function generate_restricted_conformers_best (line 597) | def generate_restricted_conformers_best(args):
function generate_poses (line 672) | def generate_poses(receptor, refmol, target_molecules, output_filename, ...
function filter_by_series (line 736) | def filter_by_series(mols, filter_series='3-aminopyridine-like'):
function filter_by_IC50s (line 754) | def filter_by_IC50s(mols):
function load_molecules (line 762) | def load_molecules(filename, append_warts=False):
function load_fragment (line 802) | def load_fragment(fragid, protonation_state, title=None):
function prepend_fragment_molecules (line 839) | def prepend_fragment_molecules(mols, fragments):
function write_molecules (line 861) | def write_molecules(mols, filename):
function read_receptor (line 876) | def read_receptor(fragid, assembly_state, protonation_state):
FILE: examples/moonshot-mainseries/03-list-absent-molecules.py
function GetFragments (line 12) | def GetFragments(mol, minbonds, maxbonds):
function GetCommonFragments (line 30) | def GetCommonFragments(mollist, frags,
function GetCoreFragment (line 57) | def GetCoreFragment(refmol, mols,
function GetFragmentScore (line 81) | def GetFragmentScore(mol):
function expand_stereochemistry_star (line 89) | def expand_stereochemistry_star(mol):
function expand_stereochemistry (line 113) | def expand_stereochemistry(mols):
function expand_protonation_states (line 145) | def expand_protonation_states(mols):
class BumpCheck (line 193) | class BumpCheck:
method __init__ (line 194) | def __init__(self, prot_mol, cutoff=2.0):
method count (line 198) | def count(self, lig_mol):
function mmff_energy (line 205) | def mmff_energy(mol):
function generate_restricted_conformers (line 222) | def generate_restricted_conformers(receptor, refmol, mol, core_smarts=No...
function has_ic50 (line 424) | def has_ic50(mol):
function get_series (line 441) | def get_series(mol):
function generate_restricted_conformers_star (line 518) | def generate_restricted_conformers_star(args):
function generate_poses (line 561) | def generate_poses(receptor, refmol, target_molecules, output_filename):
function filter_by_series (line 620) | def filter_by_series(mols, filter_series='3-aminopyridine-like'):
function filter_by_IC50s (line 638) | def filter_by_IC50s(mols):
function load_molecules (line 646) | def load_molecules(filename, append_warts=False):
function load_fragment (line 683) | def load_fragment(fragid, protonation_state, title=None):
function prepend_fragment_molecules (line 720) | def prepend_fragment_molecules(mols, fragments):
function write_molecules (line 742) | def write_molecules(mols, filename):
function read_receptor (line 757) | def read_receptor(fragid, assembly_state, protonation_state):
FILE: examples/moonshot-mainseries/molecules/filter-cdd-export.py
function pIC50 (line 34) | def pIC50(IC50_series):
function DeltaG (line 37) | def DeltaG(pIC50):
FILE: examples/moonshot-mainseries/perses/analyze-benchmark-pKa.py
function get_molecule_titles (line 14) | def get_molecule_titles(filename, add_warts=False):
function get_experimental_data (line 64) | def get_experimental_data(filename):
function get_microstate_info (line 91) | def get_microstate_info(filename):
function get_experimental_data_network (line 133) | def get_experimental_data_network(filename):
function collapse_states (line 186) | def collapse_states(perses_graph, microstates):
function get_perses_realtime_statistics (line 273) | def get_perses_realtime_statistics(basepath, trajectory_prefix='out'):
function get_perses_network_results (line 305) | def get_perses_network_results(basepath, trajectory_prefix='out'):
function solve_mle (line 393) | def solve_mle(graph):
function generate_arsenic_plots (line 410) | def generate_arsenic_plots(experimental_data_graph, perses_graph, arseni...
function display_predictions (line 494) | def display_predictions(graph):
function plot_sign_accuracy (line 540) | def plot_sign_accuracy(perses_graph, experimental_graph, filename):
FILE: examples/moonshot-mainseries/perses/extract-trajectories.py
function new_positions (line 29) | def new_positions(htf, hybrid_positions):
function old_positions (line 34) | def old_positions(htf, hybrid_positions):
function extract_single_trajectory (line 39) | def extract_single_trajectory(phase, htf, state):
function read_htfs (line 86) | def read_htfs(htf_filename):
function extract_trajectories (line 110) | def extract_trajectories(path, prefix, extract, outpath, phase, index):
FILE: examples/moonshot-mainseries/perses/run-perses.py
function load_molecules (line 6) | def load_molecules(filename, append_warts=False):
function enumerate_transformations (line 47) | def enumerate_transformations():
function cli (line 90) | def cli():
function count (line 94) | def count():
function run (line 106) | def run(index):
FILE: notebooks/plotting_tools.py
class NonequilibriumSwitchingAnalysis (line 6) | class NonequilibriumSwitchingAnalysis(object):
method __init__ (line 11) | def __init__(self, trajectory_directory, trajectory_prefix):
method get_nonequilibrium_trajectory (line 65) | def get_nonequilibrium_trajectory(self, direction, trajectory_index):
method lambda_zero_traj (line 94) | def lambda_zero_traj(self):
method lambda_one_traj (line 107) | def lambda_one_traj(self):
method cumulative_work (line 120) | def cumulative_work(self):
FILE: perses/__init__.py
function get_datadir (line 3) | def get_datadir():
FILE: perses/_version.py
function get_keywords (line 20) | def get_keywords():
class VersioneerConfig (line 33) | class VersioneerConfig:
function get_config (line 37) | def get_config():
class NotThisMethod (line 51) | class NotThisMethod(Exception):
function register_vcs_handler (line 59) | def register_vcs_handler(vcs, method): # decorator
function run_command (line 70) | def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
function versions_from_parentdir (line 105) | def versions_from_parentdir(parentdir_prefix, root, verbose):
function git_get_keywords (line 131) | def git_get_keywords(versionfile_abs):
function git_versions_from_keywords (line 160) | def git_versions_from_keywords(keywords, tag_prefix, verbose):
function git_pieces_from_vcs (line 219) | def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_comma...
function plus_or_dot (line 313) | def plus_or_dot(pieces):
function render_pep440 (line 320) | def render_pep440(pieces):
function render_pep440_pre (line 345) | def render_pep440_pre(pieces):
function render_pep440_post (line 361) | def render_pep440_post(pieces):
function render_pep440_old (line 388) | def render_pep440_old(pieces):
function render_git_describe (line 410) | def render_git_describe(pieces):
function render_git_describe_long (line 430) | def render_git_describe_long(pieces):
function render (line 450) | def render(pieces, style):
function get_versions (line 482) | def get_versions():
FILE: perses/analysis/analysis.py
class Analysis (line 39) | class Analysis(object):
method __init__ (line 43) | def __init__(self, storage_filename):
method get_environments (line 59) | def get_environments(self):
method _state_transition_to_iupac (line 73) | def _state_transition_to_iupac(self, state_transition):
method plot_work_trajectories (line 98) | def plot_work_trajectories(self, environment, filename):
method plot_sams_weights (line 137) | def plot_sams_weights(self, environment):
method plot_chemical_trajectory (line 144) | def plot_chemical_trajectory(self, environment, filename):
method get_free_energies (line 179) | def get_free_energies(self, environment):
method _get_state_transitions (line 214) | def _get_state_transitions(self):
method write_trajectory (line 252) | def write_trajectory(self, environmnent, pdb_filename):
method extract_logP_values (line 265) | def extract_logP_values(self, environment, logP_accept_component, subt...
method _prepare_logP_accept (line 307) | def _prepare_logP_accept(self, environment):
method extract_state_trajectory (line 337) | def extract_state_trajectory(self, environment):
method plot_ncmc_work_distributions (line 362) | def plot_ncmc_work_distributions(self, environment, output_filename):
method plot_exen_logp_components (line 404) | def plot_exen_logp_components(self, environment, filename_prefix=None,...
method plot_ncmc_work_old (line 478) | def plot_ncmc_work_old(self, filename):
FILE: perses/analysis/cycles.py
function pathway (line 18) | def pathway(nodes):
function get_attr (line 39) | def get_attr(G, nodeA, nodeB, attr='dg'):
function combine_errors (line 60) | def combine_errors(errors):
function cycle_closure (line 63) | def cycle_closure(G, steps, verbose=False):
function plot_comparison (line 107) | def plot_comparison(x,y,X,Y, title='',shaded=True,color='blue'):
FILE: perses/analysis/extract_trajectory.py
function get_hybrid_topology (line 12) | def get_hybrid_topology(file):
function get_positions (line 38) | def get_positions(file):
function write_trajectory (line 50) | def write_trajectory(positions, topology, outputfile='trajectory.pdb',ce...
FILE: perses/analysis/fah_analysis.py
function _strip_outliers (line 19) | def _strip_outliers(w, max_value=1e4, n_devs=5):
function _get_works (line 41) | def _get_works(df, run, project, GEN=None):
function free_energies (line 71) | def free_energies(
FILE: perses/analysis/load_simulations.py
class Simulation (line 7) | class Simulation(object):
method __init__ (line 68) | def __init__(self, directory):
method _load_data (line 104) | def _load_data(self):
method report (line 156) | def report(self):
method historic_fes (line 163) | def historic_fes(self, stepsize=100):
method sample_history (line 221) | def sample_history(self, method='binding'):
method reset_history (line 251) | def reset_history(self):
FILE: perses/analysis/resample.py
function samples_correlated (line 6) | def samples_correlated(arrays, seed=None):
function samples_uncorrelated (line 53) | def samples_uncorrelated(arrays, seed=None):
function _bootstrap (line 94) | def _bootstrap(get_samples, f, n_iters, seed):
function bootstrap_correlated (line 117) | def bootstrap_correlated(f, n_iters=100, seed=None):
function bootstrap_uncorrelated (line 154) | def bootstrap_uncorrelated(f, n_iters=100, seed=None):
FILE: perses/analysis/utils.py
function open_netcdf (line 6) | def open_netcdf(filename):
function get_offline_free_energies (line 18) | def get_offline_free_energies(filename,offline_frequency=10):
function get_t0 (line 34) | def get_t0(filename):
function plot_replica_mixing (line 44) | def plot_replica_mixing(ncfile_name, title='',filename='replicas.png'):
FILE: perses/analysis/visualization.py
function _check_pymol (line 32) | def _check_pymol():
function _check_mpy (line 39) | def _check_mpy():
class Visualization (line 61) | class Visualization(object):
method __init__ (line 85) | def __init__(self, old_pdb,
method load (line 167) | def load(self):
method format (line 214) | def format(self,
method _set_transparency (line 332) | def _set_transparency(self, old_transparency, new_transparency, old_se...
method save_frames (line 353) | def save_frames(self,
method save_mp4 (line 398) | def save_mp4(frames, outfile="movie.mp4", fps=25):
FILE: perses/annihilation/lambda_protocol.py
class LambdaProtocol (line 11) | class LambdaProtocol(object):
method __init__ (line 38) | def __init__(self, functions='default'):
method _validate_functions (line 138) | def _validate_functions(self,n=10):
method _check_for_naked_charges (line 175) | def _check_for_naked_charges(self,n=10):
method get_functions (line 196) | def get_functions(self):
method plot_functions (line 199) | def plot_functions(self,n=50):
class RESTProtocol (line 212) | class RESTProtocol(object):
method __init__ (line 221) | def __init__(self):
class RESTCapableLambdaProtocol (line 224) | class RESTCapableLambdaProtocol(object):
method __init__ (line 281) | def __init__(self, functions='default'):
class RelativeAlchemicalState (line 293) | class RelativeAlchemicalState(AlchemicalState):
class _LambdaParameter (line 312) | class _LambdaParameter(AlchemicalState._LambdaParameter):
method set_alchemical_parameters (line 322) | def set_alchemical_parameters(self, global_lambda,
class RESTState (line 337) | class RESTState(AlchemicalState):
class _LambdaParameter (line 350) | class _LambdaParameter(AlchemicalState._LambdaParameter):
method lambda_validator (line 352) | def lambda_validator(self, instance, parameter_value):
method set_alchemical_parameters (line 362) | def set_alchemical_parameters(self,
class RESTCapableRelativeAlchemicalState (line 379) | class RESTCapableRelativeAlchemicalState(AlchemicalState):
class _LambdaParameter (line 432) | class _LambdaParameter(AlchemicalState._LambdaParameter):
method lambda_validator (line 434) | def lambda_validator(self, instance, parameter_value):
method set_alchemical_parameters (line 462) | def set_alchemical_parameters(self, global_lambda, beta0, beta, lambda...
FILE: perses/annihilation/ncmc_switching.py
class NaNException (line 20) | class NaNException(Exception):
method __init__ (line 21) | def __init__(self, *args, **kwargs):
class NCMCEngine (line 24) | class NCMCEngine(object):
method __init__ (line 45) | def __init__(self, temperature=default_temperature, functions=None, ns...
method beta (line 126) | def beta(self):
method _compute_energy_contribution (line 131) | def _compute_energy_contribution(self, hybrid_thermodynamic_state, ini...
method _topology_proposal_to_thermodynamic_states (line 160) | def _topology_proposal_to_thermodynamic_states(self, topology_proposal):
method make_alchemical_system (line 185) | def make_alchemical_system(self, topology_proposal, current_positions,...
method integrate (line 223) | def integrate(self, topology_proposal, initial_sampler_state, proposed...
FILE: perses/annihilation/relative.py
class HybridTopologyFactory (line 16) | class HybridTopologyFactory(object):
method __init__ (line 65) | def __init__(self,
method _validate_disjoint_sets (line 371) | def _validate_disjoint_sets(self):
method _handle_virtual_sites (line 386) | def _handle_virtual_sites(self):
method _determine_core_atoms_in_topology (line 411) | def _determine_core_atoms_in_topology(self, topology, unique_atoms, ma...
method _determine_atom_classes (line 453) | def _determine_atom_classes(self):
method _translate_nonbonded_method_to_custom (line 494) | def _translate_nonbonded_method_to_custom(self, standard_nonbonded_met...
method _handle_constraints (line 518) | def _handle_constraints(self):
method _determine_interaction_group (line 542) | def _determine_interaction_group(self, atoms_in_interaction):
method _add_bond_force_terms (line 588) | def _add_bond_force_terms(self):
method _add_angle_force_terms (line 626) | def _add_angle_force_terms(self):
method _add_torsion_force_terms (line 698) | def _add_torsion_force_terms(self, add_custom_core_force=True, add_uni...
method _add_nonbonded_force_terms (line 741) | def _add_nonbonded_force_terms(self, add_custom_sterics_force=True):
method _nonbonded_custom_sterics_common (line 852) | def _nonbonded_custom_sterics_common(self):
method _nonbonded_custom (line 872) | def _nonbonded_custom(self, v2):
method _nonbonded_custom_mixing_rules (line 897) | def _nonbonded_custom_mixing_rules(self):
method _find_bond_parameters (line 915) | def _find_bond_parameters(self, bond_force, index1, index2):
method handle_harmonic_bonds (line 942) | def handle_harmonic_bonds(self):
method _find_angle_parameters (line 1069) | def _find_angle_parameters(self, angle_force, indices):
method _find_torsion_parameters (line 1098) | def _find_torsion_parameters(self, torsion_force, indices):
method handle_harmonic_angles (line 1131) | def handle_harmonic_angles(self):
method handle_periodic_torsion_force (line 1292) | def handle_periodic_torsion_force(self):
method handle_nonbonded (line 1386) | def handle_nonbonded(self):
method _generate_dict_from_exceptions (line 1493) | def _generate_dict_from_exceptions(self, force):
method _handle_interaction_groups (line 1517) | def _handle_interaction_groups(self):
method _handle_hybrid_exceptions (line 1562) | def _handle_hybrid_exceptions(self):
method _handle_original_exceptions (line 1660) | def _handle_original_exceptions(self):
method handle_old_new_exceptions (line 1803) | def handle_old_new_exceptions(self):
method _find_exception (line 1903) | def _find_exception(self, force, index1, index2):
method _compute_hybrid_positions (line 1930) | def _compute_hybrid_positions(self):
method _create_topology (line 1963) | def _create_topology(self):
method _impose_virtual_bonds (line 2038) | def _impose_virtual_bonds(self):
method _impose_rmsd_restraint (line 2099) | def _impose_rmsd_restraint(self):
method old_positions (line 2153) | def old_positions(self, hybrid_positions):
method new_positions (line 2175) | def new_positions(self, hybrid_positions):
method hybrid_system (line 2198) | def hybrid_system(self):
method new_to_hybrid_atom_map (line 2210) | def new_to_hybrid_atom_map(self):
method old_to_hybrid_atom_map (line 2222) | def old_to_hybrid_atom_map(self):
method hybrid_positions (line 2234) | def hybrid_positions(self):
method hybrid_topology (line 2247) | def hybrid_topology(self):
method omm_hybrid_topology (line 2259) | def omm_hybrid_topology(self):
class RepartitionedHybridTopologyFactory (line 2269) | class RepartitionedHybridTopologyFactory(HybridTopologyFactory):
method __init__ (line 2276) | def __init__(self,
method _handle_bonds (line 2447) | def _handle_bonds(self):
method _handle_angles (line 2492) | def _handle_angles(self):
method _handle_torsions (line 2538) | def _handle_torsions(self):
method _handle_nonbonded (line 2587) | def _handle_nonbonded(self):
method _handle_exceptions (line 2658) | def _handle_exceptions(self):
class RESTCapableHybridTopologyFactory (line 2701) | class RESTCapableHybridTopologyFactory(HybridTopologyFactory):
method __init__ (line 3027) | def __init__(self,
method _generate_rest_region (line 3200) | def _generate_rest_region(self):
method _build_hybrid_particles (line 3234) | def _build_hybrid_particles(self):
method _validate_disjoint_sets (line 3267) | def _validate_disjoint_sets(self):
method get_rest_identifier (line 3281) | def get_rest_identifier(self, particles):
method get_alch_identifier (line 3338) | def get_alch_identifier(self, particles):
method _create_bond_force (line 3380) | def _create_bond_force(self):
method _copy_bonds (line 3447) | def _copy_bonds(self):
method _create_angle_force (line 3542) | def _create_angle_force(self):
method _copy_angles (line 3592) | def _copy_angles(self):
method _create_torsion_force (line 3693) | def _create_torsion_force(self):
method _copy_torsions (line 3749) | def _copy_torsions(self):
method _create_electrostatics_force (line 3879) | def _create_electrostatics_force(self):
method _create_scaled_sterics_force (line 3945) | def _create_scaled_sterics_force(self):
method _create_reciprocal_space_force (line 4037) | def _create_reciprocal_space_force(self):
method _create_nonscaled_sterics_force (line 4085) | def _create_nonscaled_sterics_force(self):
method _copy_nonbondeds (line 4127) | def _copy_nonbondeds(self):
method _create_exceptions_force (line 4236) | def _create_exceptions_force(self):
method _copy_exceptions (line 4296) | def _copy_exceptions(self):
FILE: perses/annihilation/rest.py
class RESTTopologyFactory (line 18) | class RESTTopologyFactory(HybridTopologyFactory):
method __init__ (line 33) | def __init__(self, system, solute_region, use_dispersion_correction=Fa...
method _handle_constraints (line 106) | def _handle_constraints(self):
method _add_bond_force_terms (line 111) | def _add_bond_force_terms(self):
method scaling_expression (line 128) | def scaling_expression(self, nb=False):
method _add_angle_force_terms (line 140) | def _add_angle_force_terms(self):
method _add_torsion_force_terms (line 157) | def _add_torsion_force_terms(self):
method _add_nonbonded_force_terms (line 175) | def _add_nonbonded_force_terms(self):
method get_identifier (line 208) | def get_identifier(self, particles):
method _add_bonds (line 222) | def _add_bonds(self):
method _add_angles (line 232) | def _add_angles(self):
method _add_torsions (line 239) | def _add_torsions(self):
method _add_nonbondeds (line 246) | def _add_nonbondeds(self):
method REST_system (line 276) | def REST_system(self):
FILE: perses/app/cli.py
function _check_openeye_license (line 69) | def _check_openeye_license():
function _test_platform (line 75) | def _test_platform(platform_name):
function cli (line 88) | def cli(yaml, platform_name, override):
FILE: perses/app/fah_generator.py
class TimeFilter (line 18) | class TimeFilter(logging.Filter):
method filter (line 22) | def filter(self, record):
function make_neq_integrator (line 68) | def make_neq_integrator(nsteps_eq=250000, nsteps_neq=250000, neq_splitti...
function make_core_file (line 99) | def make_core_file(numSteps,
function relax_structure (line 160) | def relax_structure(temperature,
function run_neq_fah_setup (line 235) | def run_neq_fah_setup(ligand_file,
function run (line 620) | def run(yaml_filename=None):
FILE: perses/app/relative_hydration.py
function simulate_hybrid (line 12) | def simulate_hybrid(hybrid_system,functions, lambda_value, positions, ns...
function check_alchemical_hybrid_elimination_bar (line 23) | def check_alchemical_hybrid_elimination_bar(topology_proposal, old_posit...
FILE: perses/app/relative_point_mutation_setup.py
class PointMutationExecutor (line 34) | class PointMutationExecutor(object):
method __init__ (line 107) | def __init__(self,
method generate_htf (line 475) | def generate_htf(self, factory, topology_proposal, old_positions, new_...
method get_complex_htf (line 549) | def get_complex_htf(self):
method get_apo_htf (line 558) | def get_apo_htf(self):
method get_complex_rhtf_0 (line 567) | def get_complex_rhtf_0(self):
method get_apo_rhtf_0 (line 576) | def get_apo_rhtf_0(self):
method get_complex_rhtf_1 (line 585) | def get_complex_rhtf_1(self):
method get_apo_rhtf_1 (line 594) | def get_apo_rhtf_1(self):
method get_apo_rest_htf (line 603) | def get_apo_rest_htf(self):
method get_complex_rest_htf (line 612) | def get_complex_rest_htf(self):
method _solvate (line 621) | def _solvate(self,
method _handle_charge_changes (line 688) | def _handle_charge_changes(self, topology_proposal, new_positions):
FILE: perses/app/relative_setup.py
class RelativeFEPSetup (line 37) | class RelativeFEPSetup(object):
method __init__ (line 43) | def __init__(self,
method _setup_complex_phase (line 592) | def _setup_complex_phase(self):
method _generate_solvent_topologies (line 641) | def _generate_solvent_topologies(self, topology_proposal, old_positions):
method _generate_vacuum_topologies (line 730) | def _generate_vacuum_topologies(self, topology_proposal, old_positions):
method _make_new_deterministic_positions (line 799) | def _make_new_deterministic_positions(self, phase):
method _solvate_system (line 824) | def _solvate_system(self, topology, positions, model='tip3p',phase='co...
method _handle_charge_changes (line 887) | def _handle_charge_changes(self, topology_proposal, new_positions):
method _store_phase_topologies (line 919) | def _store_phase_topologies(self, phase: str):
method complex_topology_proposal (line 976) | def complex_topology_proposal(self):
method complex_old_positions (line 980) | def complex_old_positions(self):
method complex_new_positions (line 984) | def complex_new_positions(self):
method solvent_topology_proposal (line 988) | def solvent_topology_proposal(self):
method solvent_old_positions (line 992) | def solvent_old_positions(self):
method solvent_new_positions (line 996) | def solvent_new_positions(self):
method vacuum_topology_proposal (line 1000) | def vacuum_topology_proposal(self):
method vacuum_old_positions (line 1004) | def vacuum_old_positions(self):
method vacuum_new_positions (line 1008) | def vacuum_new_positions(self):
class DaskClient (line 1011) | class DaskClient(object):
method __init__ (line 1024) | def __init__(self):
method activate_client (line 1027) | def activate_client(self,
method deactivate_client (line 1053) | def deactivate_client(self):
method scatter (line 1062) | def scatter(self, df):
method deploy (line 1072) | def deploy(self, func, arguments):
method gather_results (line 1095) | def gather_results(self, futures):
method wait (line 1113) | def wait(self, futures):
class NonequilibriumSwitchingFEP (line 1123) | class NonequilibriumSwitchingFEP(DaskClient):
method __init__ (line 1128) | def __init__(self,
method compute_nonalchemical_perturbations (line 1305) | def compute_nonalchemical_perturbations(self, start, end, sampler_stat...
method instantiate_particles (line 1381) | def instantiate_particles(self,
method algorithm_4 (line 1504) | def algorithm_4(self,
method gather_neq_results (line 1668) | def gather_neq_results(self):
method compute_sMC_free_energy (line 1708) | def compute_sMC_free_energy(self):
method attempt_resample (line 1721) | def attempt_resample(self, observable = 'ESS', resampling_method = 'mu...
method ESS (line 1793) | def ESS(works_prev, works_incremental):
method CESS (line 1818) | def CESS(works_prev, works_incremental):
method multinomial_resample (line 1845) | def multinomial_resample(cumulative_works, sampler_states, num_resampl...
method binary_search (line 1878) | def binary_search(self,
method equilibrate (line 1966) | def equilibrate(self,
method modify_thermodynamic_state (line 2092) | def modify_thermodynamic_state(self, thermodynamic_state, current_lamb...
method pull_trajectory_snapshot (line 2101) | def pull_trajectory_snapshot(self, endstate):
method _adjust_for_correlation (line 2132) | def _adjust_for_correlation(self, timeseries_array: np.array):
method _endpoint_perturbations (line 2153) | def _endpoint_perturbations(self, direction = None, num_subsamples = 1...
method _alchemical_free_energy (line 2208) | def _alchemical_free_energy(self, num_subsamples = 100):
method current_free_energy_estimate (line 2230) | def current_free_energy_estimate(self):
FILE: perses/app/setup_relative_calculation.py
class TimeFilter (line 23) | class TimeFilter(logging.Filter):
method filter (line 24) | def filter(self, record):
function getSetupOptions (line 47) | def getSetupOptions(filename, override_string=None):
function get_openmm_platform (line 341) | def get_openmm_platform(platform_name=None):
function run_setup (line 372) | def run_setup(setup_options, serialize_systems=True, build_samplers=True):
function run (line 753) | def run(yaml_filename=None, override_string=None):
function _resume_run (line 991) | def _resume_run(setup_options):
function _process_overrides (line 1051) | def _process_overrides(overrides, yaml_options):
function _generate_htf (line 1093) | def _generate_htf(phase: str, topology_proposal_dictionary: dict, setup_...
function _validate_endstate_energies_for_htf (line 1134) | def _validate_endstate_energies_for_htf(hybrid_topology_factory_dict: di...
function _generate_parsed_yaml (line 1165) | def _generate_parsed_yaml(setup_options, input_yaml_file_path):
FILE: perses/bias/bias_engine.py
class BiasEngine (line 14) | class BiasEngine(object):
method __init__ (line 24) | def __init__(self, metadata):
method g_k (line 27) | def g_k(self, molecule_smiles):
class MinimizedPotentialBias (line 43) | class MinimizedPotentialBias(BiasEngine):
method __init__ (line 58) | def __init__(self, smiles_list, implicit_solvent=None, constraints=app...
method _create_molecule_list (line 69) | def _create_molecule_list(self, smiles_list):
method _create_implicit_solvent_openmm (line 92) | def _create_implicit_solvent_openmm(self, mol):
method g_k (line 122) | def g_k(self, molecule_smiles):
method precompute_gk (line 151) | def precompute_gk(self):
FILE: perses/data/constant-pH/imidazole/generate-protomers-from-smiles.py
function read_molecules (line 18) | def read_molecules(filename):
function DumpSDData (line 49) | def DumpSDData(mol):
function retrieve_url (line 58) | def retrieve_url(url, filename):
function read_molecule (line 67) | def read_molecule(filename):
function fix_mol2_resname (line 77) | def fix_mol2_resname(filename, residue_name):
function write_mol2_preserving_atomnames (line 87) | def write_mol2_preserving_atomnames(filename, molecules, residue_name):
function enumerate_conformations (line 101) | def enumerate_conformations(name, smiles=None, pdbname=None):
FILE: perses/dispersed/feptasks.py
class Particle (line 29) | class Particle():
method __init__ (line 116) | def __init__(self,
method anneal (line 244) | def anneal(self, new, num_integration_steps = 1):
method attempt_termination (line 310) | def attempt_termination(self):
method compute_incremental_work (line 333) | def compute_incremental_work(self, _lambda):
method save_configuration (line 345) | def save_configuration(self, iteration):
method launch_particle (line 378) | def launch_particle(task):
method distribute_anneal (line 444) | def distribute_anneal(task, new, num_integration_steps = 1):
method update_incremental_work (line 468) | def update_incremental_work(task, index):
method pull_sampler_state (line 480) | def pull_sampler_state(task):
method pull_cumulative_work (line 488) | def pull_cumulative_work(task):
method pull_cumulative_work_profile (line 495) | def pull_cumulative_work_profile(task):
method pull_work_increments (line 503) | def pull_work_increments(task):
method pull_current_lambda (line 516) | def pull_current_lambda(task):
method pull_shadow_work (line 528) | def pull_shadow_work(task):
method pull_timers (line 535) | def pull_timers(task):
method pull_success (line 542) | def pull_success(task):
method pull_labels (line 549) | def pull_labels(task):
method pull_last_label (line 556) | def pull_last_label(task):
method push_resamples (line 564) | def push_resamples(task, sampler_state, label, work):
method push_cumulative_work (line 577) | def push_cumulative_work(task, work):
method check_NonequilibriumFEPTask (line 585) | def check_NonequilibriumFEPTask(task):
method write_nonequilibrium_trajectory (line 618) | def write_nonequilibrium_trajectory(nonequilibrium_trajectory, traject...
function check_EquilibriumFEPTask (line 639) | def check_EquilibriumFEPTask(task):
function minimize (line 659) | def minimize(thermodynamic_state: states.ThermodynamicState, sampler_sta...
function compute_reduced_potential (line 692) | def compute_reduced_potential(thermodynamic_state: states.ThermodynamicS...
function write_nonequilibrium_trajectory (line 714) | def write_nonequilibrium_trajectory(nonequilibrium_trajectory, trajector...
function write_equilibrium_trajectory (line 735) | def write_equilibrium_trajectory(trajectory: md.Trajectory, trajectory_f...
function compute_nonalchemical_perturbation (line 759) | def compute_nonalchemical_perturbation(alchemical_thermodynamic_state: s...
function compute_timeseries (line 814) | def compute_timeseries(reduced_potentials: np.array) -> list:
function run_equilibrium (line 827) | def run_equilibrium(task):
FILE: perses/dispersed/parallel.py
class Parallelism (line 9) | class Parallelism(object):
method activate_client (line 23) | def activate_client(self,
method deactivate_client (line 81) | def deactivate_client(self):
method scatter (line 107) | def scatter(self, df, workers = None):
method deploy (line 137) | def deploy(self, func, arguments, workers = None):
method run_all (line 170) | def run_all(self, func, arguments, workers):
method gather_results (line 198) | def gather_results(self, futures, omit_errors = False):
method gather_actor_result (line 226) | def gather_actor_result(self, future):
method launch_actor (line 246) | def launch_actor(self, _class):
method progress (line 272) | def progress(self, futures):
method wait (line 291) | def wait(self, futures):
FILE: perses/dispersed/smc.py
class SequentialMonteCarlo (line 22) | class SequentialMonteCarlo():
method __init__ (line 33) | def __init__(self,
method implement_parallelism (line 187) | def implement_parallelism(self, external_parallelism, internal_paralle...
method _activate_annealing_workers (line 223) | def _activate_annealing_workers(self):
method _deactivate_annealing_workers (line 260) | def _deactivate_annealing_workers(self):
method AIS (line 281) | def AIS(self,
method sMC (line 403) | def sMC(self,
method compute_sMC_free_energy (line 712) | def compute_sMC_free_energy(self, cumulative_work_dict):
method minimize_sampler_states (line 734) | def minimize_sampler_states(self):
method pull_trajectory_snapshot (line 743) | def pull_trajectory_snapshot(self, endstate):
method equilibrate (line 772) | def equilibrate(self,
method _resample (line 916) | def _resample(self,
method compute_lambda_increment (line 978) | def compute_lambda_increment(self, new_val, sampler_states, observable...
method binary_search (line 989) | def binary_search(self,
FILE: perses/dispersed/utils.py
function check_platform (line 37) | def check_platform(platform):
function check_system (line 53) | def check_system(system):
function configure_platform (line 77) | def configure_platform(platform_name='Reference', fallback_platform_name...
function compute_survival_rate (line 120) | def compute_survival_rate(sMC_particle_ancestries):
function compute_potential_components (line 145) | def compute_potential_components(context, beta=beta, platform=DEFAULT_PL...
function minimize (line 188) | def minimize(thermodynamic_state,
function multinomial_resample (line 220) | def multinomial_resample(total_works, num_resamples):
function ESS (line 244) | def ESS(works_prev, works_incremental):
function CESS (line 266) | def CESS(works_prev, works_incremental):
function compute_timeseries (line 288) | def compute_timeseries(reduced_potentials):
function run_equilibrium (line 318) | def run_equilibrium(task):
function write_equilibrium_trajectory (line 451) | def write_equilibrium_trajectory(trajectory: md.Trajectory, trajectory_f...
function write_nonequilibrium_trajectory (line 477) | def write_nonequilibrium_trajectory(nonequilibrium_trajectory, trajector...
function compute_reduced_potential (line 498) | def compute_reduced_potential(thermodynamic_state: states.ThermodynamicS...
function create_endstates (line 522) | def create_endstates(first_thermostate, last_thermostate):
function generate_endpoint_thermodynamic_states (line 584) | def generate_endpoint_thermodynamic_states(system, topology_proposal, re...
function create_endstates_from_real_systems (line 643) | def create_endstates_from_real_systems(htf, for_testing=False):
function validate_endstate_energies (line 830) | def validate_endstate_energies(topology_proposal,
function validate_endstate_energies_point (line 951) | def validate_endstate_energies_point(input_htf, endstate=0, minimize=Fal...
function activate_LocallyOptimalAnnealing (line 1103) | def activate_LocallyOptimalAnnealing(thermodynamic_state,
function deactivate_worker_attributes (line 1141) | def deactivate_worker_attributes(remote_worker):
function call_anneal_method (line 1158) | def call_anneal_method(remote_worker,
class LocallyOptimalAnnealing (line 1190) | class LocallyOptimalAnnealing():
method initialize (line 1198) | def initialize(self,
method anneal (line 1273) | def anneal(self,
method attempt_termination (line 1419) | def attempt_termination(self, noneq_trajectory_filename):
method reset_dimensions (line 1435) | def reset_dimensions(self):
method compute_incremental_work (line 1443) | def compute_incremental_work(self, _lambda):
method update_context (line 1474) | def update_context(self, _lambda):
method save_configuration (line 1487) | def save_configuration(self, iteration, sampler_state):
FILE: perses/rjmc/atom_mapping.py
class InvalidMappingException (line 28) | class InvalidMappingException(Exception):
method __init__ (line 33) | def __init__(self, message):
class AtomMapping (line 50) | class AtomMapping(object):
method __init__ (line 89) | def __init__(self, old_mol, new_mol, new_to_old_atom_map=None, old_to_...
method __repr__ (line 133) | def __repr__(self):
method __str__ (line 136) | def __str__(self):
method __hash__ (line 139) | def __hash__(self):
method _validate (line 143) | def _validate(self):
method new_to_old_atom_map (line 168) | def new_to_old_atom_map(self):
method new_to_old_atom_map (line 173) | def new_to_old_atom_map(self, value):
method old_to_new_atom_map (line 178) | def old_to_new_atom_map(self):
method old_to_new_atom_map (line 183) | def old_to_new_atom_map(self, value):
method n_mapped_atoms (line 188) | def n_mapped_atoms(self):
method render_image (line 192) | def render_image(self, filename, format=None, width=1200, height=600):
method _ipython_display_ (line 322) | def _ipython_display_(self):
method creates_or_breaks_rings (line 327) | def creates_or_breaks_rings(self):
method unmap_partially_mapped_cycles (line 366) | def unmap_partially_mapped_cycles(self):
method preserve_chirality (line 470) | def preserve_chirality(self):
class AtomMapper (line 560) | class AtomMapper(object):
method __init__ (line 653) | def __init__(self,
method get_all_mappings (line 751) | def get_all_mappings(self, old_mol, new_mol):
method get_best_mapping (line 957) | def get_best_mapping(self, old_mol, new_mol):
method get_sampled_mapping (line 1008) | def get_sampled_mapping(self, old_mol, new_mol):
method propose_mapping (line 1043) | def propose_mapping(old_mol, new_mol):
method score_mapping (line 1079) | def score_mapping(self, atom_mapping):
method generate_atom_mapping_from_positions (line 1186) | def generate_atom_mapping_from_positions(self, old_mol, new_mol):
method _get_all_maps (line 1262) | def _get_all_maps(old_oemol, new_oemol,
method _create_pattern_to_target_map (line 1343) | def _create_pattern_to_target_map(old_oemol, new_oemol, match, matchin...
method _create_atom_mapping (line 1379) | def _create_atom_mapping(old_oemol, new_oemol, match, matching_criteri...
method _assign_ring_ids (line 1433) | def _assign_ring_ids(oemol, max_ring_size=10, assign_atoms=True, assig...
method _get_scaffold (line 1493) | def _get_scaffold(oemol, adjustHcount=False):
function _convert_opemol_to_offmol (line 1559) | def _convert_opemol_to_offmol(oemol, allow_undefined_stereo: bool=False,...
function _convert_positions_to_angstroms (line 1835) | def _convert_positions_to_angstroms(positions):
FILE: perses/rjmc/coordinate_numba.py
function _cross_vec3 (line 5) | def _cross_vec3(a, b):
function _norm (line 13) | def _norm(a):
function _rotation_matrix (line 18) | def _rotation_matrix(axis, angle):
function internal_to_cartesian (line 46) | def internal_to_cartesian(bond_position, angle_position, torsion_positio...
function torsion_scan (line 79) | def torsion_scan(bond_position, angle_position, torsion_position, intern...
function calculate_angle (line 88) | def calculate_angle(atom_position, bond_position, angle_position):
function cartesian_to_internal (line 104) | def cartesian_to_internal(atom_position, bond_position, angle_position, ...
FILE: perses/rjmc/coordinate_tools.py
function _rotation_matrix (line 3) | def _rotation_matrix(axis, angle):
function _cartesian_to_internal (line 26) | def _cartesian_to_internal(atom_position, bond_position, angle_position,...
function _internal_to_cartesian (line 69) | def _internal_to_cartesian(bond_position, angle_position, torsion_positi...
FILE: perses/rjmc/geometry.py
function check_dimensionality (line 34) | def check_dimensionality(quantity, compatible_units):
class GeometryEngine (line 71) | class GeometryEngine(object):
method __init__ (line 81) | def __init__(self, metadata=None, storage=None):
method propose (line 85) | def propose(self, top_proposal, current_positions, beta):
method logp_reverse (line 103) | def logp_reverse(self, top_proposal, new_coordinates, old_coordinates,...
class FFAllAngleGeometryEngine (line 128) | class FFAllAngleGeometryEngine(GeometryEngine):
method __init__ (line 160) | def __init__(self,
method propose (line 195) | def propose(self, top_proposal, current_positions, beta, validate_ener...
method logp_reverse (line 250) | def logp_reverse(self, top_proposal, new_coordinates, old_coordinates,...
method _write_partial_pdb (line 295) | def _write_partial_pdb(self, pdbfile, topology, positions, atoms_with_...
method _logp_propose (line 327) | def _logp_propose(self, top_proposal, old_positions, beta, new_positio...
method _corrected_reduced_potential (line 707) | def _corrected_reduced_potential(self, growth_system_generator, positi...
method _define_no_nb_system (line 746) | def _define_no_nb_system(self,
method _copy_positions (line 822) | def _copy_positions(self, atoms_with_positions, top_proposal, current_...
method _get_relevant_bond (line 854) | def _get_relevant_bond(self, atom1, atom2):
method _get_bond_constraint (line 883) | def _get_bond_constraint(self, atom1, atom2, system):
method _get_relevant_angle (line 917) | def _get_relevant_angle(self, atom1, atom2, atom3):
method _add_bond_units (line 961) | def _add_bond_units(self, bond):
method _add_angle_units (line 988) | def _add_angle_units(self, angle):
method _add_torsion_units (line 1015) | def _add_torsion_units(self, torsion):
method _rotation_matrix (line 1042) | def _rotation_matrix(self, axis, angle):
method _cartesian_to_internal (line 1077) | def _cartesian_to_internal(self, atom_position, bond_position, angle_p...
method _internal_to_cartesian (line 1135) | def _internal_to_cartesian(self, bond_position, angle_position, torsio...
method _bond_log_pmf (line 1191) | def _bond_log_pmf(self, bond, beta, n_divisions):
method _bond_logp (line 1257) | def _bond_logp(self, r, bond, beta, n_divisions):
method _propose_bond (line 1301) | def _propose_bond(self, bond, beta, n_divisions):
method _angle_log_pmf (line 1345) | def _angle_log_pmf(self, angle, beta, n_divisions):
method _angle_logp (line 1413) | def _angle_logp(self, theta, angle, beta, n_divisions):
method _propose_angle (line 1457) | def _propose_angle(self, angle, beta, n_divisions):
method _torsion_scan (line 1500) | def _torsion_scan(self, torsion_atom_indices, positions, r, theta, n_d...
method _torsion_log_pmf (line 1557) | def _torsion_log_pmf(self, growth_context, torsion_atom_indices, posit...
method _propose_torsion (line 1655) | def _propose_torsion(self, growth_context, torsion_atom_indices, posit...
method _torsion_logp (line 1710) | def _torsion_logp(self, growth_context, torsion_atom_indices, position...
class GeometrySystemGenerator (line 1759) | class GeometrySystemGenerator(object):
method __init__ (line 1769) | def __init__(self,
method set_growth_parameter_index (line 2136) | def set_growth_parameter_index(self, growth_parameter_index, context=N...
method get_modified_system (line 2145) | def get_modified_system(self):
method _determine_extra_torsions (line 2157) | def _determine_extra_torsions(self,
method adjust_phase (line 2354) | def adjust_phase(self, phase):
method _select_torsions_without_h (line 2380) | def _select_torsions_without_h(self, torsion_list):
method _determine_extra_angles (line 2403) | def _determine_extra_angles(self, angle_force, reference_topology, gro...
method _calculate_growth_idx (line 2475) | def _calculate_growth_idx(self, particle_indices, growth_indices):
class NetworkXProposalOrder (line 2500) | class NetworkXProposalOrder(object):
method __init__ (line 2505) | def __init__(self, topology_proposal, direction="forward"):
method _create_reference_connectivity_graph (line 2566) | def _create_reference_connectivity_graph(self):
method determine_proposal_order (line 2583) | def determine_proposal_order(self):
method _propose_atoms_in_order (line 2637) | def _propose_atoms_in_order(self, atom_group):
class NoTorsionError (line 2705) | class NoTorsionError(Exception):
method __init__ (line 2706) | def __init__(self, message):
FILE: perses/rjmc/topology_proposal.py
function add_method (line 35) | def add_method(object, function):
function set_residue_oemol_and_openmm_topology_attributes (line 48) | def set_residue_oemol_and_openmm_topology_attributes(object, residue_oem...
function _get_networkx_molecule (line 75) | def _get_networkx_molecule(self):
function augment_openmm_topology (line 140) | def augment_openmm_topology(topology, residue_oemol, residue_topology, r...
function append_topology (line 158) | def append_topology(destination_topology, source_topology, exclude_resid...
function deepcopy_topology (line 192) | def deepcopy_topology(source_topology):
class TopologyProposal (line 206) | class TopologyProposal(object):
method __init__ (line 279) | def __init__(self,
method new_topology (line 311) | def new_topology(self):
method new_system (line 314) | def new_system(self):
method old_topology (line 317) | def old_topology(self):
method old_system (line 320) | def old_system(self):
method logp_proposal (line 323) | def logp_proposal(self):
method new_to_old_atom_map (line 326) | def new_to_old_atom_map(self):
method old_to_new_atom_map (line 329) | def old_to_new_atom_map(self):
method unique_new_atoms (line 332) | def unique_new_atoms(self):
method unique_old_atoms (line 335) | def unique_old_atoms(self):
method new_alchemical_atoms (line 338) | def new_alchemical_atoms(self):
method old_alchemical_atoms (line 341) | def old_alchemical_atoms(self):
method new_environment_atoms (line 344) | def new_environment_atoms(self):
method old_environment_atoms (line 347) | def old_environment_atoms(self):
method n_atoms_new (line 350) | def n_atoms_new(self):
method n_atoms_old (line 353) | def n_atoms_old(self):
method new_chemical_state_key (line 356) | def new_chemical_state_key(self):
method old_chemical_state_key (line 359) | def old_chemical_state_key(self):
method old_residue_name (line 362) | def old_residue_name(self):
method new_residue_name (line 365) | def new_residue_name(self):
method metadata (line 368) | def metadata(self):
method core_new_to_old_atom_map (line 371) | def core_new_to_old_atom_map(self):
class ProposalEngine (line 374) | class ProposalEngine(object):
method __init__ (line 392) | def __init__(self, system_generator, proposal_metadata=None, always_ch...
method propose (line 397) | def propose(self, current_system, current_topology, current_metadata=N...
method compute_state_key (line 418) | def compute_state_key(self, topology):
method chemical_state_list (line 435) | def chemical_state_list(self):
class PolymerProposalEngine (line 438) | class PolymerProposalEngine(ProposalEngine):
method _get_neutrals (line 451) | def _get_neutrals(aminos, positive, negative):
method __init__ (line 458) | def __init__(self, system_generator, chain_id, proposal_metadata=None,...
method generate_oemol_from_pdb_template (line 485) | def generate_oemol_from_pdb_template(pdbfile):
method _get_charge_difference (line 501) | def _get_charge_difference(current_resname, new_resname):
method propose (line 531) | def propose(self,
method _find_adjacent_residue_atoms (line 725) | def _find_adjacent_residue_atoms(self, old_topology, new_topology, mut...
method _choose_mutant (line 783) | def _choose_mutant(self, topology, metadata):
method _generate_residue_map (line 804) | def _generate_residue_map(self, topology, index_to_new_residues):
method _identify_differences (line 824) | def _identify_differences(self, topology, residue_map):
method _delete_atoms (line 939) | def _delete_atoms(self, topology, to_delete):
method _add_new_atoms (line 982) | def _add_new_atoms(self, topology, missing_atoms, missing_bonds, resid...
method _is_residue_equal (line 1046) | def _is_residue_equal(self, residue, other_residue):
method _construct_atom_map (line 1059) | def _construct_atom_map(self,
method _get_mol_atom_matches (line 1191) | def _get_mol_atom_matches(self, current_molecule, proposed_molecule, f...
method compute_state_key (line 1275) | def compute_state_key(self, topology):
method validate_core_atoms_with_system (line 1292) | def validate_core_atoms_with_system(topology_proposal):
class PointMutationEngine (line 1389) | class PointMutationEngine(PolymerProposalEngine):
method __init__ (line 1406) | def __init__(self,
method _choose_mutant (line 1478) | def _choose_mutant(self, topology, metadata):
method _undo_old_mutants (line 1525) | def _undo_old_mutants(self, topology, chain_id, old_key):
method _choose_mutation_from_allowed (line 1565) | def _choose_mutation_from_allowed(self, topology, chain_id, allowed_mu...
method _propose_mutation (line 1673) | def _propose_mutation(self, topology, chain_id, index_to_new_residues):
method _mutable_residues (line 1749) | def _mutable_residues(self, chain):
method _save_mutations (line 1753) | def _save_mutations(self, topology, index_to_new_residues):
method _compute_mutant_key (line 1770) | def _compute_mutant_key(self,
class PeptideLibraryEngine (line 1821) | class PeptideLibraryEngine(PolymerProposalEngine):
method __init__ (line 1838) | def __init__(self, system_generator, library, chain_id, proposal_metad...
method _choose_mutant (line 1844) | def _choose_mutant(self, topology, metadata):
method _one_to_three_letter_code (line 1892) | def _one_to_three_letter_code(self, residue_one_letter):
class SmallMoleculeSetProposalEngine (line 1918) | class SmallMoleculeSetProposalEngine(ProposalEngine):
method __init__ (line 1960) | def __init__(self, list_of_oemols, system_generator, residue_name='MOL...
method propose (line 2014) | def propose(self,
method canonicalize_smiles (line 2186) | def canonicalize_smiles(smiles):
method _topology_to_smiles (line 2210) | def _topology_to_smiles(self, topology):
method compute_state_key (line 2247) | def compute_state_key(self, topology):
method _find_mol_start_index (line 2266) | def _find_mol_start_index(self, topology):
method _build_new_topology (line 2292) | def _build_new_topology(self, current_receptor_topology, oemol_proposed):
method _remove_small_molecule (line 2324) | def _remove_small_molecule(self, topology):
method _constraint_repairs (line 2349) | def _constraint_repairs(atom_map, old_system, new_system, old_topology...
method _propose_molecule (line 2414) | def _propose_molecule(self, system, topology, current_mol_id, exclude_...
method _calculate_probability_matrix (line 2462) | def _calculate_probability_matrix(self):
method chemical_state_list (line 2512) | def chemical_state_list(self):
method clean_molecule_list (line 2517) | def clean_molecule_list(smiles_list, atom_opts, bond_opts):
FILE: perses/samplers/multistate.py
class HybridCompatibilityMixin (line 22) | class HybridCompatibilityMixin(object):
method __init__ (line 28) | def __init__(self, *args, hybrid_factory=None, **kwargs):
method setup (line 33) | def setup(self, n_states, temperature, storage_file, minimisation_step...
class HybridSAMSSampler (line 120) | class HybridSAMSSampler(HybridCompatibilityMixin, sams.SAMSSampler):
method __init__ (line 125) | def __init__(self, *args, hybrid_factory=None, **kwargs):
class HybridRepexSampler (line 130) | class HybridRepexSampler(HybridCompatibilityMixin, replicaexchange.Repli...
method __init__ (line 135) | def __init__(self, *args, hybrid_factory=None, **kwargs):
FILE: perses/samplers/samplers.py
function log_sum_exp (line 43) | def log_sum_exp(a_n):
class ExpandedEnsembleSampler (line 60) | class ExpandedEnsembleSampler(object):
method __init__ (line 129) | def __init__(self, sampler, topology, state_key, proposal_engine, geom...
method state_keys (line 218) | def state_keys(self):
method get_log_weight (line 221) | def get_log_weight(self, state_key):
method _system_to_thermodynamic_state (line 244) | def _system_to_thermodynamic_state(self, system):
method _geometry_forward (line 261) | def _geometry_forward(self, topology_proposal, old_sampler_state):
method _geometry_reverse (line 295) | def _geometry_reverse(self, topology_proposal, new_sampler_state, old_...
method _ncmc_hybrid (line 320) | def _ncmc_hybrid(self, topology_proposal, old_sampler_state, new_sampl...
method _geometry_ncmc_geometry (line 353) | def _geometry_ncmc_geometry(self, topology_proposal, sampler_state, ol...
method update_positions (line 442) | def update_positions(self, n_iterations=1):
method update_state (line 448) | def update_state(self):
method update (line 510) | def update(self):
method run (line 532) | def run(self, niterations=1):
method update_statistics (line 544) | def update_statistics(self):
class SAMSSampler (line 556) | class SAMSSampler(object):
method __init__ (line 607) | def __init__(self, sampler, logZ=None, log_target_probabilities=None, ...
method state_keys (line 687) | def state_keys(self):
method _num_dof_compensation (line 690) | def _num_dof_compensation(self, smiles):
method update_sampler (line 725) | def update_sampler(self):
method update_logZ_estimates (line 731) | def update_logZ_estimates(self):
method update (line 776) | def update(self):
method run (line 790) | def run(self, niterations=1):
class MultiTargetDesign (line 806) | class MultiTargetDesign(object):
method __init__ (line 823) | def __init__(self, target_samplers, storage=None, verbose=False):
method state_keys (line 868) | def state_keys(self):
method update_samplers (line 871) | def update_samplers(self):
method update_target_probabilities (line 878) | def update_target_probabilities(self):
method update (line 908) | def update(self):
method run (line 922) | def run(self, niterations=1):
class ProtonationStateSampler (line 940) | class ProtonationStateSampler(object):
method __init__ (line 956) | def __init__(self, complex_sampler, solvent_sampler, log_state_penalti...
method state_keys (line 990) | def state_keys(self):
method update_samplers (line 993) | def update_samplers(self):
method update_target_probabilities (line 1000) | def update_target_probabilities(self):
method update (line 1011) | def update(self):
method run (line 1025) | def run(self, niterations=1):
FILE: perses/samplers/thermodynamics.py
class ThermodynamicState (line 51) | class ThermodynamicState(object):
method __init__ (line 87) | def __init__(self, system, temperature, pressure=None):
method _create_context (line 151) | def _create_context(self, platform=None):
method _cleanup_context (line 180) | def _cleanup_context(self):
method _compute_potential (line 185) | def _compute_potential(self, coordinates, box_vectors):
method reduced_potential (line 198) | def reduced_potential(self, coordinates, box_vectors=None, platform=No...
method beta (line 307) | def beta(self):
method reduced_potential_multiple (line 310) | def reduced_potential_multiple(self, coordinates_list, box_vectors_lis...
method is_compatible_with (line 409) | def is_compatible_with(self, state):
method __repr__ (line 458) | def __repr__(self):
method __str__ (line 485) | def __str__(self):
function volume (line 490) | def volume(box_vectors):
FILE: perses/storage/storage.py
class NetCDFStorage (line 35) | class NetCDFStorage(object):
method __init__ (line 39) | def __init__(self, filename, mode='w'):
method _find_group (line 61) | def _find_group(self):
method _encode_string (line 73) | def _encode_string(string, encoding='ascii'):
method sync (line 81) | def sync(self):
method close (line 86) | def close(self):
method write_configuration (line 91) | def write_configuration(self, varname, positions, topology, iteration=...
method write_object (line 159) | def write_object(self, varname, obj, iteration=None):
method get_object (line 186) | def get_object(self, envname, modname, varname, iteration=None):
method write_quantity (line 217) | def write_quantity(self, varname, value, iteration=None):
method write_array (line 242) | def write_array(self, varname, array, iteration=None):
class NetCDFStorageView (line 296) | class NetCDFStorageView(NetCDFStorage):
method __init__ (line 299) | def __init__(self, storage, envname=None, modname=None):
FILE: perses/tests/benchmark.py
function plot_logPs (line 39) | def plot_logPs(logps, molecule_name, scheme, component):
function benchmark_exen_ncmc_protocol (line 74) | def benchmark_exen_ncmc_protocol(analyses, molecule_name, scheme):
function benchmark_ncmc_work_during_protocol (line 121) | def benchmark_ncmc_work_during_protocol():
FILE: perses/tests/conftest.py
function pytest_addoption (line 5) | def pytest_addoption(parser):
function pytest_configure (line 11) | def pytest_configure(config):
function pytest_collection_modifyitems (line 17) | def pytest_collection_modifyitems(config, items):
function in_tmpdir (line 26) | def in_tmpdir(tmpdir):
function input_yaml_template (line 31) | def input_yaml_template():
function input_template_obj_default_selection (line 61) | def input_template_obj_default_selection(input_yaml_template):
function input_template_not_water_selection (line 67) | def input_template_not_water_selection(input_template_obj_default_select...
FILE: perses/tests/test_GPU.py
function test_gpu_platforms (line 6) | def test_gpu_platforms(platform_type):
FILE: perses/tests/test_analysis.py
function test_analysis (line 29) | def test_analysis():
FILE: perses/tests/test_atom_mapping.py
class TestAtomMapping (line 20) | class TestAtomMapping(unittest.TestCase):
method setUp (line 22) | def setUp(self):
method test_create (line 29) | def test_create(self):
method test_validation_fail (line 39) | def test_validation_fail(self):
method test_set_and_get_mapping (line 53) | def test_set_and_get_mapping(self):
method test_repr (line 64) | def test_repr(self):
method test_str (line 68) | def test_str(self):
method test_render_image (line 72) | def test_render_image(self):
method test_ring_breaking_detection (line 79) | def test_ring_breaking_detection(self):
method test_unmap_partially_mapped_cycles (line 92) | def test_unmap_partially_mapped_cycles(self):
method test_preserve_chirality (line 109) | def test_preserve_chirality(self):
class TestAtomMapper (line 127) | class TestAtomMapper(unittest.TestCase):
method setUp (line 128) | def setUp(self):
method test_molecular_atom_mapping (line 137) | def test_molecular_atom_mapping(self):
method test_map_strategy (line 166) | def test_map_strategy(self):
method test_sampled_mappings (line 196) | def test_sampled_mappings(self):
method test_generate_atom_mapping_from_positions (line 225) | def test_generate_atom_mapping_from_positions(self):
method test_atom_mappings_moonshot (line 245) | def test_atom_mappings_moonshot(self):
method test_simple_heterocycle_mapping (line 279) | def test_simple_heterocycle_mapping(self):
method test_mapping_strength_levels (line 300) | def test_mapping_strength_levels(self):
FILE: perses/tests/test_cli.py
function default_input_yaml_template_cli (line 12) | def default_input_yaml_template_cli():
function input_template_obj_cli (line 49) | def input_template_obj_cli(default_input_yaml_template_cli):
function input_template_obj_tip5p_cli (line 54) | def input_template_obj_tip5p_cli(input_template_obj_cli):
function test_dummy_cli_with_override (line 62) | def test_dummy_cli_with_override(input_params, in_tmpdir, request):
function test_s3_yaml_read (line 94) | def test_s3_yaml_read(in_tmpdir):
FILE: perses/tests/test_coordinate_numba.py
function test_coordinate_conversion (line 21) | def test_coordinate_conversion():
function test_openmm_dihedral (line 46) | def test_openmm_dihedral():
function test_try_random_itoc (line 117) | def test_try_random_itoc():
FILE: perses/tests/test_fah.py
function test_pipeline_small_molecule (line 32) | def test_pipeline_small_molecule():
function test_pipeline_small_molecule_solvent (line 60) | def test_pipeline_small_molecule_solvent():
function test_pipeline_protein (line 83) | def test_pipeline_protein():
function test_core_file (line 107) | def test_core_file():
function test_neq_integrator (line 119) | def test_neq_integrator():
FILE: perses/tests/test_geometry_engine.py
class GeometryTestSystem (line 81) | class GeometryTestSystem(object):
method topology (line 103) | def topology(self):
method system (line 107) | def system(self):
method structure (line 111) | def structure(self):
method growth_order (line 115) | def growth_order(self):
method positions (line 119) | def positions(self):
method energy (line 123) | def energy(self):
class FourAtomValenceTestSystem (line 127) | class FourAtomValenceTestSystem(GeometryTestSystem):
method __init__ (line 147) | def __init__(self, bond=True, angle=True, torsion=True):
method internal_coordinates (line 231) | def internal_coordinates(self):
method internal_coordinates (line 239) | def internal_coordinates(self, internal_coordinates):
method bond_parameters (line 248) | def bond_parameters(self):
method angle_parameters (line 253) | def angle_parameters(self):
method torsion_parameters (line 258) | def torsion_parameters(self):
function test_propose_bond (line 262) | def test_propose_bond():
function test_propose_angle (line 311) | def test_propose_angle():
function test_bond_logp (line 361) | def test_bond_logp():
function test_angle_logp (line 420) | def test_angle_logp():
function test_add_bond_units (line 486) | def test_add_bond_units():
function test_add_angle_units (line 514) | def test_add_angle_units():
function test_add_torsion_units (line 545) | def test_add_torsion_units():
function test_torsion_scan (line 575) | def test_torsion_scan():
function test_torsion_log_discrete_pdf (line 622) | def test_torsion_log_discrete_pdf():
function calculate_torsion_discrete_log_pdf_manually (line 659) | def calculate_torsion_discrete_log_pdf_manually(beta, torsion, phis):
function test_torsion_logp (line 695) | def test_torsion_logp():
function test_propose_torsion (line 741) | def test_propose_torsion():
function _get_internal_from_omm (line 794) | def _get_internal_from_omm(atom_coords, bond_coords, angle_coords, torsi...
function oemol_to_openmm_system (line 864) | def oemol_to_openmm_system(oemol):
function oemol_to_openmm_system_amber (line 869) | def oemol_to_openmm_system_amber(oemol, molecule_name):
function align_molecules (line 890) | def align_molecules(mol1, mol2):
function test_mutate_from_all_to_all (line 917) | def test_mutate_from_all_to_all(): # TODO: fix protein mutations
function test_propose_lysozyme_ligands (line 979) | def test_propose_lysozyme_ligands(): # TODO: fix protein mutations
function test_propose_kinase_inhibitors (line 994) | def test_propose_kinase_inhibitors(): # TODO: fix protein mutations
function run_proposals (line 1001) | def run_proposals(proposal_list):
function make_geometry_proposal_array (line 1042) | def make_geometry_proposal_array(smiles_list, forcefield=['data/gaff.xml...
function load_pdbid_to_openmm (line 1090) | def load_pdbid_to_openmm(pdbid):
function _guessFileFormat (line 1112) | def _guessFileFormat(file, filename):
function test_existing_coordinates (line 1132) | def test_existing_coordinates():
function run_logp_reverse (line 1155) | def run_logp_reverse():
function _get_capped_amino_acid (line 1186) | def _get_capped_amino_acid(amino_acid='ALA'):
function _tleap_all (line 1221) | def _tleap_all():
function _oemol_from_residue (line 1226) | def _oemol_from_residue(res):
function _print_failed_SMILES (line 1252) | def _print_failed_SMILES(failed_mol_list):
function _generate_ffxmls (line 1258) | def _generate_ffxmls():
class LinearValenceTestSystem (line 1286) | class LinearValenceTestSystem(GeometryTestSystem):
method __init__ (line 1293) | def __init__(self, bond=True, angle=True, torsion=True, n_atoms=4, add...
method internal_coordinates (line 1418) | def internal_coordinates(self):
method internal_coordinates (line 1425) | def internal_coordinates(self, internal_coordinates):
method bond_parameters (line 1436) | def bond_parameters(self):
method angle_parameters (line 1440) | def angle_parameters(self):
method torsion_parameters (line 1444) | def torsion_parameters(self):
class AnalyticalBeadSystems (line 1450) | class AnalyticalBeadSystems(object):
method __init__ (line 1456) | def __init__(self, transformation, num_iterations):
method convert_to_md (line 1482) | def convert_to_md(self, openmm_positions):
method minimize (line 1501) | def minimize(self, system, positions):
method compute_rp (line 1525) | def compute_rp(self, system, positions):
method create_simple_topology_proposal (line 1552) | def create_simple_topology_proposal(self, sys_pos_top, n_atoms_initial...
method run_rj_simple_system (line 1602) | def run_rj_simple_system(self, configurations_initial, topology_propos...
method create_iid_bead_systems (line 1647) | def create_iid_bead_systems(self, printer=False):
method forward_transformation (line 1687) | def forward_transformation(self, iid_positions_A, printer=False):
method backward_transformation (line 1719) | def backward_transformation(self, proposed_positions, printer=False):
method work_comparison (line 1754) | def work_comparison(self, printer=False):
function test_AnalyticalBeadSystems (line 1789) | def test_AnalyticalBeadSystems(transformation=[[3,4], [4,5], [3,5]], num...
function test_logp_forward_check_for_vacuum_topology_proposal (line 1826) | def test_logp_forward_check_for_vacuum_topology_proposal(current_mol_nam...
FILE: perses/tests/test_lambda_protocol.py
function test_lambda_protocol (line 14) | def test_lambda_protocol():
function test_lambda_protocol_failure_ends (line 32) | def test_lambda_protocol_failure_ends():
function test_lambda_protocol_naked_charges (line 37) | def test_lambda_protocol_naked_charges():
FILE: perses/tests/test_ncmc_integrator.py
function collect_switching_data (line 22) | def collect_switching_data(system, positions, functions, temperature, co...
FILE: perses/tests/test_parallel.py
function test_Parallelism_local (line 18) | def test_Parallelism_local():
function test_Parallelism_distributed (line 40) | def test_Parallelism_distributed():
function run_parallelism (line 57) | def run_parallelism(_parallel, data):
function dummy_function (line 122) | def dummy_function(_arg):
FILE: perses/tests/test_relative.py
function run_hybrid_endpoint_overlap (line 39) | def run_hybrid_endpoint_overlap(topology_proposal, current_positions, ne...
function calculate_cross_variance (line 89) | def calculate_cross_variance(all_results):
function check_result (line 108) | def check_result(results, threshold=3.0, neffmin=10):
function test_networkx_proposal_order (line 129) | def test_networkx_proposal_order():
function test_explosion (line 140) | def test_explosion():
function test_vacuum_overlap_with_constraints (line 151) | def test_vacuum_overlap_with_constraints():
function test_valence_overlap (line 157) | def test_valence_overlap():
function test_bonds_angles_overlap (line 166) | def test_bonds_angles_overlap():
function test_sterics_overlap (line 175) | def test_sterics_overlap():
function test_simple_overlap_pairs (line 184) | def test_simple_overlap_pairs(pairs=None):
function test_simple_overlap (line 214) | def test_simple_overlap(name1='pentane', name2='butane', forcefield_kwar...
function test_hostguest_overlap (line 244) | def test_hostguest_overlap():
function test_difficult_overlap (line 260) | def test_difficult_overlap():
function run_endpoint_perturbation (line 289) | def run_endpoint_perturbation(lambda_thermodynamic_state, nonalchemical_...
function compare_energies (line 405) | def compare_energies(mol_name="naphthalene", ref_mol_name="benzene",atom...
function test_compare_energies (line 473) | def test_compare_energies():
function test_position_output (line 479) | def test_position_output():
function test_generate_endpoint_thermodynamic_states (line 497) | def test_generate_endpoint_thermodynamic_states():
function HybridTopologyFactory_energies (line 515) | def HybridTopologyFactory_energies(current_mol = 'toluene', proposed_mol...
function test_HybridTopologyFactory_energies (line 571) | def test_HybridTopologyFactory_energies(molecule_perturbation_list = [['...
function test_RMSD_restraint (line 579) | def test_RMSD_restraint():
function RepartitionedHybridTopologyFactory_energies (line 656) | def RepartitionedHybridTopologyFactory_energies(topology, chain, system,...
function test_RepartitionedHybridTopologyFactory_energies (line 758) | def test_RepartitionedHybridTopologyFactory_energies():
function flattenedHybridTopologyFactory_energies (line 796) | def flattenedHybridTopologyFactory_energies(topology, chain, system, pos...
function test_flattenedHybridTopologyFactory_energies (line 932) | def test_flattenedHybridTopologyFactory_energies():
function run_RESTCapableHybridTopologyFactory_energies (line 948) | def run_RESTCapableHybridTopologyFactory_energies(test_name, phase, use_...
function test_RESTCapableHybridTopologyFactory_energies (line 1021) | def test_RESTCapableHybridTopologyFactory_energies():
function test_RESTCapableHybridTopologyFactory_energies_GPU (line 1038) | def test_RESTCapableHybridTopologyFactory_energies_GPU():
function run_unsampled_endstate_energies (line 1055) | def run_unsampled_endstate_energies(test_name, use_point_energies=True, ...
function test_unsampled_endstate_energies (line 1192) | def test_unsampled_endstate_energies():
function test_unsampled_endstate_energies_GPU (line 1204) | def test_unsampled_endstate_energies_GPU():
class TestHybridTopologyFactory (line 1223) | class TestHybridTopologyFactory:
method test_custom_nonbonded_cutoff (line 1225) | def test_custom_nonbonded_cutoff(self):
FILE: perses/tests/test_relative_point_mutation_setup.py
function test_PointMutationExecutor (line 4) | def test_PointMutationExecutor():
function test_PointMutationExecutor_endstate_validation (line 35) | def test_PointMutationExecutor_endstate_validation():
function test_PointMutationExecutor_solvated (line 63) | def test_PointMutationExecutor_solvated():
function test_PointMutationExecutor_without_counterion (line 92) | def test_PointMutationExecutor_without_counterion():
FILE: perses/tests/test_relative_setup.py
function generate_example_waterbox_states (line 21) | def generate_example_waterbox_states(temperature=300.0*unit.kelvin, pres...
function test_parsed_yaml_generation (line 45) | def test_parsed_yaml_generation():
function test_run_nonequilibrium_switching_move (line 84) | def test_run_nonequilibrium_switching_move():
function test_run_cdk2_iterations_repex (line 158) | def test_run_cdk2_iterations_repex():
function test_run_bace_spectator (line 209) | def test_run_bace_spectator():
function test_relative_setup_charge_change (line 259) | def test_relative_setup_charge_change():
function test_relative_setup_solvent_padding (line 310) | def test_relative_setup_solvent_padding():
function test_relative_setup_list_ligand_input (line 329) | def test_relative_setup_list_ligand_input():
function test_relative_setup_topologies_storage (line 366) | def test_relative_setup_topologies_storage(tmp_path):
FILE: perses/tests/test_repex.py
function test_RESTCapableHybridTopologyFactory_repex_neutral_mutation (line 8) | def test_RESTCapableHybridTopologyFactory_repex_neutral_mutation():
function test_RESTCapableHybridTopologyFactory_repex_charge_mutation (line 95) | def test_RESTCapableHybridTopologyFactory_repex_charge_mutation():
function test_RESTCapableHybridTopologyFactory_repex_neutral_transformation (line 203) | def test_RESTCapableHybridTopologyFactory_repex_neutral_transformation():
function test_RESTCapableHybridTopologyFactory_repex_charge_transformation (line 315) | def test_RESTCapableHybridTopologyFactory_repex_charge_transformation():
FILE: perses/tests/test_rest.py
function compare_energy_components (line 25) | def compare_energy_components(rest_system, other_system, positions, plat...
function test_bookkeeping (line 75) | def test_bookkeeping():
function compare_energies (line 139) | def compare_energies(REST_system, other_system, positions, rest_atoms, T...
function test_energy_scaling (line 240) | def test_energy_scaling():
FILE: perses/tests/test_resume.py
function test_cli_resume_repex (line 24) | def test_cli_resume_repex(input_params, request):
function test_resume_small_molecule (line 63) | def test_resume_small_molecule():
function test_resume_protein_mutation_with_checkpoint (line 137) | def test_resume_protein_mutation_with_checkpoint(tmp_path):
function test_resume_protein_mutation_no_checkpoint (line 206) | def test_resume_protein_mutation_no_checkpoint(tmp_path):
FILE: perses/tests/test_samplers.py
function test_valence (line 32) | def test_valence():
function test_testsystems_gh_actions (line 68) | def test_testsystems_gh_actions():
function test_testsystems_advanced (line 82) | def test_testsystems_advanced():
function run_samplers (line 89) | def run_samplers(testsystem_names, niterations=5):
FILE: perses/tests/test_smc.py
function sMC_setup (line 43) | def sMC_setup():
function test_local_AIS (line 112) | def test_local_AIS():
function test_configure_platform (line 166) | def test_configure_platform():
function test_compute_survival_rate (line 173) | def test_compute_survival_rate():
function test_multinomial_resample (line 194) | def test_multinomial_resample():
function test_ESS (line 205) | def test_ESS():
function test_CESS (line 213) | def test_CESS():
function test_compute_timeseries (line 221) | def test_compute_timeseries():
function test_create_endstates (line 229) | def test_create_endstates():
FILE: perses/tests/test_storage.py
function test_storage_create (line 27) | def test_storage_create():
function test_storage_append (line 34) | def test_storage_append():
function test_sync (line 43) | def test_sync():
function test_storage_view (line 50) | def test_storage_view():
function test_write_quantity (line 61) | def test_write_quantity():
function test_write_array (line 76) | def test_write_array():
function test_write_object (line 100) | def test_write_object():
function run_sampler (line 126) | def run_sampler(sampler, niterations):
function test_storage_with_samplers (line 131) | def test_storage_with_samplers():
FILE: perses/tests/test_topology_proposal.py
function test_small_molecule_proposals (line 43) | def test_small_molecule_proposals():
function test_small_molecule_constraint_repair_mapping (line 78) | def test_small_molecule_constraint_repair_mapping():
function load_pdbid_to_openmm (line 128) | def load_pdbid_to_openmm(pdbid):
function _guessFileFormat (line 150) | def _guessFileFormat(file, filename):
function create_simple_protein_system_generator (line 170) | def create_simple_protein_system_generator():
function create_insulin_topology_engine (line 181) | def create_insulin_topology_engine(chain_id = 'A', allowed_mutations = N...
function generate_atp (line 197) | def generate_atp(phase = 'vacuum'):
function generate_dipeptide_top_pos_sys (line 252) | def generate_dipeptide_top_pos_sys(topology,
function test_mutate_from_alanine (line 409) | def test_mutate_from_alanine():
function test_protein_atom_maps (line 428) | def test_protein_atom_maps():
function test_specify_allowed_mutants (line 492) | def test_specify_allowed_mutants():
function test_propose_self (line 539) | def test_propose_self():
function test_run_point_mutation_propose (line 571) | def test_run_point_mutation_propose():
function test_alanine_dipeptide_map (line 599) | def test_alanine_dipeptide_map():
function test_mutate_from_every_amino_to_every_other (line 643) | def test_mutate_from_every_amino_to_every_other():
function test_limiting_allowed_residues (line 777) | def test_limiting_allowed_residues():
function test_always_change (line 815) | def test_always_change():
function test_run_peptide_library_engine (line 868) | def test_run_peptide_library_engine():
function test_protein_counterion_topology_fix_positive (line 902) | def test_protein_counterion_topology_fix_positive():
function test_protein_counterion_topology_fix_negitive (line 949) | def test_protein_counterion_topology_fix_negitive():
function test_protein_counterion_topology_fix_zero (line 997) | def test_protein_counterion_topology_fix_zero():
FILE: perses/tests/test_utils.py
function test_get_data_filename (line 19) | def test_get_data_filename(datafile='data/gaff2.xml'):
function test_extractPositionsFromOEMol (line 40) | def test_extractPositionsFromOEMol(molecule=smiles_to_oemol('CC')):
function test_giveOpenmmPositionsToOEMol (line 66) | def test_giveOpenmmPositionsToOEMol(positions=None, molecule=smiles_to_o...
function test_OEMol_to_omm_ff (line 105) | def test_OEMol_to_omm_ff(molecule=smiles_to_oemol('CC')):
function run_oemol_test_suite (line 147) | def run_oemol_test_suite(iupac='ethane'):
function test_generate_expression (line 181) | def test_generate_expression():
FILE: perses/tests/test_visualization.py
function test_protein_mutation (line 11) | def test_protein_mutation():
function test_small_molecule (line 31) | def test_small_molecule():
FILE: perses/tests/testsystems.py
class PersesTestSystem (line 63) | class PersesTestSystem(object):
method __init__ (line 91) | def __init__(self, storage_filename=None, mode='w', ncmc_nsteps=5, mcm...
class AlanineDipeptideTestSystem (line 124) | class AlanineDipeptideTestSystem(PersesTestSystem):
method __init__ (line 163) | def __init__(self, constraints=app.HBonds, **kwargs):
class AlanineDipeptideValenceTestSystem (line 280) | class AlanineDipeptideValenceTestSystem(PersesTestSystem):
method __init__ (line 319) | def __init__(self, **kwargs):
function load_via_pdbfixer (line 408) | def load_via_pdbfixer(filename=None, pdbid=None):
class T4LysozymeMutationTestSystem (line 422) | class T4LysozymeMutationTestSystem(PersesTestSystem):
method __init__ (line 461) | def __init__(self, **kwargs):
class MybTestSystem (line 629) | class MybTestSystem(PersesTestSystem):
method __init__ (line 667) | def __init__(self, **kwargs):
class AblImatinibResistanceTestSystem (line 800) | class AblImatinibResistanceTestSystem(PersesTestSystem):
method __init__ (line 838) | def __init__(self, **kwargs):
class AblAffinityTestSystem (line 979) | class AblAffinityTestSystem(PersesTestSystem):
method __init__ (line 1019) | def __init__(self, **kwargs):
class AblImatinibProtonationStateTestSystem (line 1193) | class AblImatinibProtonationStateTestSystem(PersesTestSystem):
method __init__ (line 1231) | def __init__(self, **kwargs):
class ImidazoleProtonationStateTestSystem (line 1418) | class ImidazoleProtonationStateTestSystem(PersesTestSystem):
method __init__ (line 1456) | def __init__(self, **kwargs):
function minimize_wrapper (line 1641) | def minimize_wrapper(testsystem):
class SmallMoleculeLibraryTestSystem (line 1664) | class SmallMoleculeLibraryTestSystem(PersesTestSystem):
method __init__ (line 1705) | def __init__(self, constraints=app.HBonds, premapped_json_dict=None, *...
class AlkanesTestSystem (line 1829) | class AlkanesTestSystem(SmallMoleculeLibraryTestSystem):
method __init__ (line 1833) | def __init__(self, **kwargs):
class KinaseInhibitorsTestSystem (line 1837) | class KinaseInhibitorsTestSystem(SmallMoleculeLibraryTestSystem):
method __init__ (line 1841) | def __init__(self, **kwargs):
class T4LysozymeInhibitorsTestSystem (line 1858) | class T4LysozymeInhibitorsTestSystem(SmallMoleculeLibraryTestSystem):
method read_smiles (line 1862) | def read_smiles(self, filename):
method __init__ (line 1874) | def __init__(self, **kwargs):
class FusedRingsTestSystem (line 1903) | class FusedRingsTestSystem(SmallMoleculeLibraryTestSystem):
method __init__ (line 1907) | def __init__(self, **kwargs):
class ValenceSmallMoleculeLibraryTestSystem (line 1911) | class ValenceSmallMoleculeLibraryTestSystem(PersesTestSystem):
method __init__ (line 1951) | def __init__(self, **kwargs):
method _canonicalize_smiles (line 2044) | def _canonicalize_smiles(self, list_of_smiles):
function check_topologies (line 2075) | def check_topologies(testsystem):
function checktestsystem (line 2091) | def checktestsystem(testsystem_class):
function test_testsystems (line 2099) | def test_testsystems():
function run_t4_inhibitors (line 2112) | def run_t4_inhibitors():
function run_alkanes (line 2131) | def run_alkanes():
function run_t4 (line 2145) | def run_t4():
function run_myb (line 2163) | def run_myb():
function run_abl_imatinib_resistance (line 2178) | def run_abl_imatinib_resistance():
function run_kinase_inhibitors (line 2196) | def run_kinase_inhibitors():
function run_valence_system (line 2210) | def run_valence_system():
function run_alanine_system (line 2222) | def run_alanine_system(sterics=False):
function test_valence_write_pdb_ncmc_switching (line 2241) | def test_valence_write_pdb_ncmc_switching():
function run_abl_affinity_write_pdb_ncmc_switching (line 2249) | def run_abl_affinity_write_pdb_ncmc_switching():
function run_constph_abl (line 2271) | def run_constph_abl():
function run_imidazole (line 2307) | def run_imidazole():
function run_fused_rings (line 2328) | def run_fused_rings():
FILE: perses/tests/utils.py
function enter_temp_directory (line 44) | def enter_temp_directory():
class NaNException (line 58) | class NaNException(Exception):
function quantity_is_finite (line 62) | def quantity_is_finite(quantity):
function compare_at_lambdas (line 82) | def compare_at_lambdas(context, functions):
function get_atoms_with_undefined_stereocenters (line 115) | def get_atoms_with_undefined_stereocenters(molecule, verbose=False):
function has_undefined_stereocenters (line 154) | def has_undefined_stereocenters(molecule, verbose=False):
function enumerate_undefined_stereocenters (line 193) | def enumerate_undefined_stereocenters(molecule, verbose=False):
function test_sanitizeSMILES (line 242) | def test_sanitizeSMILES():
function compute_potential (line 266) | def compute_potential(system, positions, platform=None):
function generate_solvated_hybrid_test_topology (line 294) | def generate_solvated_hybrid_test_topology(current_mol_name="naphthalene...
function generate_vacuum_hostguest_proposal (line 429) | def generate_vacuum_hostguest_proposal(current_mol_name="B2", proposed_m...
function validate_rjmc_work_variance (line 489) | def validate_rjmc_work_variance(top_prop, positions, geometry_method = 0...
function validate_endstate_energies_md (line 607) | def validate_endstate_energies_md(input_htf, T_max=300 * unit.kelvin, en...
function validate_unsampled_endstates_point (line 749) | def validate_unsampled_endstates_point(htf, hybrid_system, endstate=0, m...
function validate_unsampled_endstates_md (line 831) | def validate_unsampled_endstates_md(htf, hybrid_system, endstate=0, n_st...
function track_torsions (line 937) | def track_torsions(hybrid_factory):
FILE: perses/utils/charge_changing.py
function modify_atom_classes (line 9) | def modify_atom_classes(water_atoms, topology_proposal):
function get_charge_difference (line 30) | def get_charge_difference(current_oemol, new_oemol):
function get_water_indices (line 53) | def get_water_indices(charge_diff,
function get_ion_and_water_parameters (line 105) | def get_ion_and_water_parameters(system, topology, positive_ion_name="NA...
function transform_waters_into_ions (line 169) | def transform_waters_into_ions(water_atoms, system, charge_diff, particl...
FILE: perses/utils/data.py
function get_data_filename (line 12) | def get_data_filename(relative_path):
function generate_gaff_xml (line 39) | def generate_gaff_xml():
function forcefield_directory (line 63) | def forcefield_directory():
function load_smi (line 77) | def load_smi(smi_file,index=None):
function serialize (line 103) | def serialize(item, filename):
FILE: perses/utils/openeye.py
function system_generator_wrapper (line 19) | def system_generator_wrapper(oemols,
function smiles_to_oemol (line 57) | def smiles_to_oemol(smiles, title='MOL', max_confs=1):
function iupac_to_oemol (line 113) | def iupac_to_oemol(iupac, title='MOL', max_confs=1):
function extractPositionsFromOEMol (line 157) | def extractPositionsFromOEMol(molecule,units=unit.angstrom):
function giveOpenmmPositionsToOEMol (line 177) | def giveOpenmmPositionsToOEMol(positions, molecule):
function OEMol_to_omm_ff (line 201) | def OEMol_to_omm_ff(molecule, system_generator):
function createSystemFromIUPAC (line 225) | def createSystemFromIUPAC(iupac_name, title="MOL", **system_generator_kw...
function createSystemFromSMILES (line 263) | def createSystemFromSMILES(smiles,title='MOL', **system_generator_kwargs):
function describe_oemol (line 298) | def describe_oemol(mol):
function createOEMolFromSDF (line 323) | def createOEMolFromSDF(sdf_filename, index=0, add_hydrogens=True, allow_...
function calculate_mol_similarity (line 374) | def calculate_mol_similarity(molA, molB):
function createSMILESfromOEMol (line 392) | def createSMILESfromOEMol(molecule):
function generate_unique_atom_names (line 401) | def generate_unique_atom_names(molecule):
function has_undefined_stereocenters (line 447) | def has_undefined_stereocenters(mol):
function generate_expression (line 478) | def generate_expression(list):
FILE: perses/utils/smallmolecules.py
function sanitizeSMILES (line 11) | def sanitizeSMILES(smiles_list, mode='drop', verbose=False):
function canonicalize_SMILES (line 91) | def canonicalize_SMILES(smiles_list):
function show_topology (line 119) | def show_topology(topology):
function render_single_molecule (line 138) | def render_single_molecule(filename, molecule, width=1200, height=600):
function render_atom_mapping (line 157) | def render_atom_mapping(filename, molecule1, molecule2, new_to_old_atom_...
function render_protein_residue_atom_mapping (line 275) | def render_protein_residue_atom_mapping(topology_proposal, filename, wid...
function generate_ligands_figure (line 302) | def generate_ligands_figure(molecules,figsize=None,filename='ligands.png'):
FILE: perses/utils/url_utils.py
function retrieve_file_url (line 22) | def retrieve_file_url(url, retries=5):
function fetch_url_contents (line 44) | def fetch_url_contents(url, retries=5):
FILE: setup.py
function find_package_data (line 32) | def find_package_data(data_root, package_root):
FILE: versioneer.py
class VersioneerConfig (line 285) | class VersioneerConfig:
function get_root (line 289) | def get_root():
function get_config_from_root (line 328) | def get_config_from_root(root):
class NotThisMethod (line 357) | class NotThisMethod(Exception):
function register_vcs_handler (line 366) | def register_vcs_handler(vcs, method): # decorator
function run_command (line 377) | def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
function git_get_keywords (line 941) | def git_get_keywords(versionfile_abs):
function git_versions_from_keywords (line 970) | def git_versions_from_keywords(keywords, tag_prefix, verbose):
function git_pieces_from_vcs (line 1029) | def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_comma...
function do_vcs_install (line 1123) | def do_vcs_install(manifest_in, versionfile_source, ipy):
function versions_from_parentdir (line 1161) | def versions_from_parentdir(parentdir_prefix, root, verbose):
function versions_from_file (line 1204) | def versions_from_file(filename):
function write_to_version_file (line 1221) | def write_to_version_file(filename, versions):
function plus_or_dot (line 1232) | def plus_or_dot(pieces):
function render_pep440 (line 1239) | def render_pep440(pieces):
function render_pep440_pre (line 1264) | def render_pep440_pre(pieces):
function render_pep440_post (line 1280) | def render_pep440_post(pieces):
function render_pep440_old (line 1307) | def render_pep440_old(pieces):
function render_git_describe (line 1329) | def render_git_describe(pieces):
function render_git_describe_long (line 1349) | def render_git_describe_long(pieces):
function render (line 1369) | def render(pieces, style):
class VersioneerBadRootError (line 1401) | class VersioneerBadRootError(Exception):
function get_versions (line 1405) | def get_versions(verbose=False):
function get_version (line 1481) | def get_version():
function get_cmdclass (line 1486) | def get_cmdclass(cmdclass=None):
function do_setup (line 1730) | def do_setup():
function scan_setup_py (line 1812) | def scan_setup_py():
Copy disabled (too large)
Download .json
Condensed preview — 291 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (47,133K chars).
[
{
"path": ".codecov.yml",
"chars": 258,
"preview": "# Codecov configuration to make it a bit less noisy\ncoverage:\n status:\n patch: false\n project:\n default:\n "
},
{
"path": ".gitattributes",
"chars": 32,
"preview": "perses/_version.py export-subst\n"
},
{
"path": ".github/pull_request_template.md",
"chars": 493,
"preview": "## Description\n\n<!-- Describe your changes in detail. -->\n\n## Motivation and context\n\n<!--- Why is this change required?"
},
{
"path": ".github/workflows/CI.yaml",
"chars": 3084,
"preview": "name: CI\n\non:\n merge_group:\n pull_request:\n branches:\n - \"main\"\n - \"0.10.*\"\n schedule:\n # nightly tes"
},
{
"path": ".github/workflows/docker.yaml",
"chars": 6926,
"preview": "# This workflow uses actions that are not certified by GitHub.\n# They are provided by a third-party and are governed by\n"
},
{
"path": ".github/workflows/rc-check.yaml",
"chars": 716,
"preview": "on:\n schedule:\n # nightly tests, 2 am\n - cron: \"0 2 * * *\"\n\njobs:\n check-rc:\n runs-on: ubuntu-latest\n name: \"C"
},
{
"path": ".github/workflows/rc-test.yaml",
"chars": 2083,
"preview": "name: OpenMM RC Test\non:\n workflow_dispatch:\n\njobs:\n rc-test:\n runs-on: ubuntu-latest\n\n strategy:\n fail-fas"
},
{
"path": ".github/workflows/self-hosted-gpu-test.yml",
"chars": 4540,
"preview": "name: self-hosted-gpu-test\non:\n push:\n branches:\n - main\n - \"0.10.x\"\n workflow_dispatch:\n schedule:\n "
},
{
"path": ".gitignore",
"chars": 2107,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "CITATION.cff",
"chars": 1606,
"preview": "# This CITATION.cff file was generated with cffinit.\n# Visit https://bit.ly/cffinit to generate yours today!\n\ncff-versio"
},
{
"path": "LICENSE",
"chars": 1115,
"preview": "MIT License\n\nCopyright (c) 2015-2017 Chodera lab // Memorial Sloan Kettering Cancer Center\n\nPermission is hereby granted"
},
{
"path": "MANIFEST.in",
"chars": 49,
"preview": "include versioneer.py\ninclude perses/_version.py\n"
},
{
"path": "README.md",
"chars": 3508,
"preview": "<!--- [](https://travis-ci.org/choderal"
},
{
"path": "basesetup.py",
"chars": 12512,
"preview": "from __future__ import print_function, absolute_import\nimport os\nimport sys\nimport imp\nimport json\nimport shutil\nimport "
},
{
"path": "benchmarks/LSF-job-template.sh",
"chars": 770,
"preview": "#!/bin/bash\n#BSUB -P \"tyk2-benchmark\"\n#BSUB -J \"perses-benchmark-[1-24]\"\n#BSUB -n 1\n#BSUB -R rusage[mem=8]\n#BSUB -R span"
},
{
"path": "benchmarks/README.md",
"chars": 1648,
"preview": "# Perses benchmarks\n\nThis subdirectory exposes a CLI tool for running automated benchmarks from\n[OpenFF's protein ligand"
},
{
"path": "benchmarks/benchmark_analysis.py",
"chars": 9140,
"preview": "\"\"\"\nScript to perform analysis of perses simulations executed using run_benchmarks.py script.\n\nIntended to be used on sy"
},
{
"path": "benchmarks/run_benchmarks.py",
"chars": 6712,
"preview": "#!/usr/bin/env python\n\n\"\"\"\nCLI utility to automatically run benchmarks using data from the open force field protein-liga"
},
{
"path": "benchmarks/template.yaml",
"chars": 1994,
"preview": "# Path to protein file\nprotein_pdb: null\n# Path to ligand SDF file\nligand_file: null\n# Indices of old and new ligands wi"
},
{
"path": "devtools/README.md",
"chars": 932,
"preview": "Developer Notes / Tools\n=======================\n\nAssorted notes for developers.\n\nHow to do a release\n-------------------"
},
{
"path": "devtools/conda-envs/test_env.yaml",
"chars": 903,
"preview": "name: test\nchannels:\n - conda-forge\n - openeye\ndependencies:\n - ambertools <23\n - arsenic\n - autograd\n - click\n -"
},
{
"path": "devtools/scripts/initialize_conda.sh",
"chars": 164,
"preview": "case $CI_OS in\n windows*)\n eval \"$(${CONDA}/condabin/conda.bat shell.bash hook)\";;\n *)\n eval \"$(${CO"
},
{
"path": "devtools/test.smi",
"chars": 9,
"preview": "CCC\nCCCC\n"
},
{
"path": "docker/Dockerfile",
"chars": 1301,
"preview": "FROM mambaorg/micromamba:latest\n\nLABEL org.opencontainers.image.source = \"https://github.com/choderalab/perses\"\nLABEL or"
},
{
"path": "docker/Dockerfile-add-license",
"chars": 56,
"preview": "FROM choderalab/perses:dev\nADD oe_license.txt /openeye/\n"
},
{
"path": "docker/README.md",
"chars": 4089,
"preview": "# Perses Container\n\nThe container can be downloaded with `docker pull ghcr.io/choderalab/perses:latest`\n\n## OpenEye Lice"
},
{
"path": "docs/Makefile",
"chars": 603,
"preview": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS =\nSPHI"
},
{
"path": "docs/_static/README.md",
"chars": 44,
"preview": "Blank file to have git ingest this directory"
},
{
"path": "docs/analysis.rst",
"chars": 228,
"preview": ".. _analysis:\n\nAnalysis\n********\n\nAnalysis methods for perses simulations.\n\nCache objects\n-------------\n\n.. currentmodul"
},
{
"path": "docs/annihilation.rst",
"chars": 13005,
"preview": ".. _annihilation:\n\nAlchemical transformations\n**************************\n\nTools for nonequilibrium alchemical transforma"
},
{
"path": "docs/bias.rst",
"chars": 216,
"preview": ".. _bias:\n\nBias engine\n***********\n\nBias engine for sampling chemical space\n\n.. currentmodule:: perses.bias\n.. autosumma"
},
{
"path": "docs/changelog.rst",
"chars": 22859,
"preview": ".. _changelog:\n\n***************\nRelease history\n***************\n\nThis section lists features and improvements of note in"
},
{
"path": "docs/conf.py",
"chars": 6395,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n#\n# perses documentation build configuration file, created by\n# sphinx-qu"
},
{
"path": "docs/environment.yml",
"chars": 144,
"preview": "name: perses-docs\nchannels:\n - conda-forge\n - defaults\ndependencies:\n - python\n - setuptools\n - numpy\n - numpydoc\n"
},
{
"path": "docs/examples.rst",
"chars": 6993,
"preview": ".. _examples:\n\nExamples\n********\n\nAll examples are located in ``perses/examples``. These are designed to demonstrate the"
},
{
"path": "docs/index.rst",
"chars": 3040,
"preview": ".. perses documentation master file, created by\n sphinx-quickstart on Sun May 14 17:09:48 2017.\n You can adapt this "
},
{
"path": "docs/installation.rst",
"chars": 1664,
"preview": ".. _installation:\n\nInstallation\n************\n\nInstalling via `conda`\n======================\n\nThe simplest way to install"
},
{
"path": "docs/rjmc.rst",
"chars": 1898,
"preview": ".. _rjmc:\n\nMolecular geometry generation via RJMC\n**************************************\n\nReversible jump Monte Carlo (R"
},
{
"path": "docs/samplers.rst",
"chars": 309,
"preview": ".. _samplers:\n\nSampler stack\n*************\n\nSamplers for driving sampling over conformations or chemical states.\n\n.. cur"
},
{
"path": "docs/storage.rst",
"chars": 198,
"preview": ".. _storage:\n\nStorage handling\n****************\n\nStorange handling driver\n\n.. currentmodule:: perses.storage\n.. autosumm"
},
{
"path": "examples/README.md",
"chars": 1073,
"preview": "Examples\n========\nThis directory contains examples of the different modules in perses that can are used expanded\nensembl"
},
{
"path": "examples/atom-mapping/Atom-mapping.ipynb",
"chars": 6939678,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Experimenting with the `AtomMappe"
},
{
"path": "examples/barnase-barstar-neq-switching/README.md",
"chars": 575,
"preview": "# Run neq switching for a barnase:barstar mutation (T42A in barstar)\nThis script shows how to perform a non-equilibrium "
},
{
"path": "examples/barnase-barstar-neq-switching/run_example.py",
"chars": 7774,
"preview": "import logging\nimport numpy as np\nfrom openmmtools.integrators import PeriodicNonequilibriumIntegrator\nfrom openmmtools."
},
{
"path": "examples/dipeptide-mutation-repex-rest/README.md",
"chars": 1569,
"preview": "# Barnase-Barstar protein-protein interaction example\n\nThis example is based on the tools and work by Ivy Zhang in https"
},
{
"path": "examples/dipeptide-mutation-repex-rest/configfile",
"chars": 160,
"preview": "-np 1 -env CUDA_VISIBLE_DEVICES 0 run_repex.py results_dir solvent 36 10000 300\n-np 1 -env CUDA_VISIBLE_DEVICES 1 run_re"
},
{
"path": "examples/dipeptide-mutation-repex-rest/generate_htfs.py",
"chars": 3747,
"preview": "import os\nimport pickle\nimport argparse\nfrom pathlib import Path\n\nimport openmm\nfrom openmm import unit, app\nfrom perses"
},
{
"path": "examples/dipeptide-mutation-repex-rest/hostfile",
"chars": 12,
"preview": "node1\nnode1\n"
},
{
"path": "examples/dipeptide-mutation-repex-rest/run_repex.py",
"chars": 5266,
"preview": "import os\nimport pickle\nimport argparse\nimport logging\nfrom pathlib import Path\n\nfrom simtk import openmm\nfrom simtk.ope"
},
{
"path": "examples/dipeptide-neq-switching/README.md",
"chars": 514,
"preview": "# Run neq switching for a protein mutation (ALA->ASP dipeptide)\nThis script shows how to perform a non-equilibrium switc"
},
{
"path": "examples/dipeptide-neq-switching/run_example.py",
"chars": 7348,
"preview": "import logging\nimport numpy as np\nfrom openmmtools.integrators import PeriodicNonequilibriumIntegrator\nfrom openmmtools."
},
{
"path": "examples/kinase-neq-switching/README.md",
"chars": 584,
"preview": "# Run neq switching for a NTRK1:entrectinib mutation (G613V in NTRK1)\nThis script shows how to perform a non-equilibrium"
},
{
"path": "examples/kinase-neq-switching/run_example.py",
"chars": 8879,
"preview": "import logging\nimport numpy as np\nfrom openmmtools.integrators import PeriodicNonequilibriumIntegrator\nfrom openmmtools."
},
{
"path": "examples/moonshot-mainseries/00-prep-receptor.py",
"chars": 20236,
"preview": "\"\"\"\nPrepare all SARS-CoV-2 Mpro structures for docking and simulation in monomer and dimer forms and desired protonation"
},
{
"path": "examples/moonshot-mainseries/01-simulate-receptors.py",
"chars": 10282,
"preview": "\"\"\"\nRuns a simulation with OpenMM.\n\"\"\"\nimport sys\n\n# Configure logging\nimport logging\nfrom rich.logging import RichHandl"
},
{
"path": "examples/moonshot-mainseries/02-generate-poses-posit.py",
"chars": 30021,
"preview": "#!/usr/bin/env python\n\n\"\"\"\nGenerate poses for relative free energy calculations using fragment structures\n\n\"\"\"\nfrom open"
},
{
"path": "examples/moonshot-mainseries/02-generate-poses.py",
"chars": 35236,
"preview": "#!/usr/bin/env python\n\n\"\"\"\nGenerate poses for relative free energy calculations using fragment structures\n\n\"\"\"\nfrom open"
},
{
"path": "examples/moonshot-mainseries/03-list-absent-molecules.py",
"chars": 29996,
"preview": "#!/usr/bin/env python\n\n\"\"\"\nGenerate poses for relative free energy calculations using fragment structures\n\n\"\"\"\nfrom open"
},
{
"path": "examples/moonshot-mainseries/README.md",
"chars": 3473,
"preview": "# Relative free energy calculations of main medicinal chemistry milestone compounds for COVID Mooonshot\n\n## Prerequisite"
},
{
"path": "examples/moonshot-mainseries/molecules/CDD CSV Export.csv",
"chars": 1422,
"preview": "Molecule Name,Canonical PostEra ID,suspected_SMILES,ProteaseAssay_Fluorescence_Dose-Response_Weizmann: IC50 (µM),Proteas"
},
{
"path": "examples/moonshot-mainseries/molecules/filter-cdd-export.py",
"chars": 3243,
"preview": "#!/bin/env python\n\"\"\"\nFilter CDD export for main medicinal chemistry series\n\nhttps://app.collaborativedrug.com/vaults/55"
},
{
"path": "examples/moonshot-mainseries/molecules/mainseries.csv",
"chars": 1115,
"preview": "SMILES,Title,pIC50,dpIC50,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL_STDERR,EXP_BINDING_A"
},
{
"path": "examples/moonshot-mainseries/molecules/step1.csv",
"chars": 536,
"preview": "SMILES,Title,pIC50,dpIC50,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL_STDERR,EXP_BINDING_A"
},
{
"path": "examples/moonshot-mainseries/molecules/step2.csv",
"chars": 553,
"preview": "SMILES,Title,pIC50,dpIC50,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL_STDERR,EXP_BINDING_A"
},
{
"path": "examples/moonshot-mainseries/molecules/step3.csv",
"chars": 573,
"preview": "SMILES,Title,pIC50,dpIC50,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL_STDERR,EXP_BINDING_A"
},
{
"path": "examples/moonshot-mainseries/molecules/step4.csv",
"chars": 600,
"preview": "SMILES,Title,pIC50,dpIC50,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL,EXP_BINDING_AFFINITY_IN_KCAL_PER_MOL_STDERR,EXP_BINDING_A"
},
{
"path": "examples/moonshot-mainseries/perses/analyze-benchmark-pKa.py",
"chars": 25070,
"preview": "\"\"\"\nAnalyze perses calculations for a benchmark set of ligands annotated with experimental data\n\n\"\"\"\n\n# SDF filename con"
},
{
"path": "examples/moonshot-mainseries/perses/extract-trajectories.py",
"chars": 9436,
"preview": "\"\"\"\nExtract replica or state trajectories from a perses replica exchange simulation.\n\nThis requires the same version of "
},
{
"path": "examples/moonshot-mainseries/perses/run-perses.py",
"chars": 4408,
"preview": "#!/usr/bin/env python\n\"\"\"\nRun perses\n\"\"\"\n\ndef load_molecules(filename, append_warts=False):\n \"\"\"\n Read molecules f"
},
{
"path": "examples/moonshot-mainseries/perses/submit-all.sh",
"chars": 857,
"preview": "#!/bin/bash\n#BSUB -P \"asap\"\n#BSUB -J \"mainseries[1-33]\"\n#BSUB -n 1\n#BSUB -R rusage[mem=8]\n#BSUB -R span[hosts=1]\n#BSUB -"
},
{
"path": "examples/moonshot-mainseries/perses/template.yaml",
"chars": 2198,
"preview": "# Path to protein file\nprotein_pdb: ../receptors/dimer/Mpro-x2646_0A_bound-His41(0)-Cys145(0)-His163(0)-protein.pdb\n\n# P"
},
{
"path": "examples/moonshot-mainseries/setup.yaml",
"chars": 2267,
"preview": "---\n# Parameters for manual COVID Moonshot setup scripts\n\nname: mainseries-retrospective\n\n# Path to fragalysis source st"
},
{
"path": "examples/protein-ligand-repex/cli/README.md",
"chars": 1293,
"preview": "# Run tyk2 protein-ligand example\nThe files in this directory are the input files needed to run a single transformation "
},
{
"path": "examples/protein-ligand-repex/cli/protein-ligand.yaml",
"chars": 2157,
"preview": "# Path to protein file\nprotein_pdb: tyk2_protein.pdb\n\n# Path to ligand SDF file\nligand_file: tyk2_ligands.sdf\n\n# Indices"
},
{
"path": "examples/protein-ligand-repex/cli/scripts_utils/cleanup.sh",
"chars": 90,
"preview": "#!/bin/env bash\n\nrm -rf 1ns_lig*\nrm -f out_*.{stderr,stdout}\nrm -f parsed-*-template.yaml\n"
},
{
"path": "examples/protein-ligand-repex/cli/scripts_utils/run_star_map.sh",
"chars": 301,
"preview": "#!/usr/bin/env bash\n\nset -xeuo pipefail\n\nold_ligand_idx=0\nfor new_ligand_idx in $(seq 1 10)\ndo \n perses-cli --yaml te"
},
{
"path": "examples/protein-ligand-repex/cli/scripts_utils/submit-dense-map.sh",
"chars": 1103,
"preview": "#!/bin/bash\n#BSUB -P \"perses-tyk2\"\n#BSUB -J \"perses-tyk2-5ns-[1-100]\"\n#BSUB -n 1\n#BSUB -R rusage[mem=8]\n#BSUB -R span[ho"
},
{
"path": "examples/protein-ligand-repex/cli/scripts_utils/submit-star-map-serial.sh",
"chars": 1077,
"preview": "#!/bin/bash\n#BSUB -P \"perses-tyk2\"\n#BSUB -J \"perses-benchmark-tyk2-5ns-[1-14]\"\n#BSUB -n 1\n#BSUB -R rusage[mem=8]\n#BSUB -"
},
{
"path": "examples/protein-ligand-repex/cli/tyk2_ligands.sdf",
"chars": 58556,
"preview": "lig_ejm_54\n 3D\n Schrodinger Suite 2022-3.\n 37 38 0 0 1 0 999 V2000\n -4.7602 -2.796"
},
{
"path": "examples/protein-ligand-repex/cli/tyk2_protein.pdb",
"chars": 391080,
"preview": "HEADER TRANSFERASE/TRANSFERASE INHIBITOR 08-AUG-12 4GIH\nTITLE TYK2 (JH1) IN COMPLEX WITH\nTITLE 2 2,6-D"
},
{
"path": "notebooks/Analyze_results.ipynb",
"chars": 36449,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Nonequilibrium Switching Free Ene"
},
{
"path": "notebooks/Harmonic oscillators example.ipynb",
"chars": 159960,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"### Modified self-adjusted mixture "
},
{
"path": "notebooks/README.md",
"chars": 147,
"preview": "# IPython notebooks\n\n* `Harmonic oscillators example.ipynb` - modified form of self-adjusted mixture sampling for more c"
},
{
"path": "notebooks/plotting_tools.py",
"chars": 5310,
"preview": "import numpy as np\nimport mdtraj as md\nimport os\nimport glob\n\nclass NonequilibriumSwitchingAnalysis(object):\n \"\"\"\n "
},
{
"path": "notes/README.md",
"chars": 156,
"preview": "# LaTeX notes deriving acceptance criteria\n\nThe latest version of these notes are on Overleaf: [view-only link](https://"
},
{
"path": "notes/chodera-research.bib",
"chars": 114230,
"preview": "@article{shirts:jcp:2005:comparison-of-estimators,\n title={Comparison of efficiency and bias of free energies computed "
},
{
"path": "notes/manuscript.tex",
"chars": 33300,
"preview": "% PRL look and style (easy on the eyes)\n\\RequirePackage[hyphens]{url}\n\\documentclass[aps,pre,twocolumn,nofootinbib,super"
},
{
"path": "notes/prsty.bst",
"chars": 19884,
"preview": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n% begin prsty.bs"
},
{
"path": "perses/README.md",
"chars": 454,
"preview": "Perses\n======\nPackage for simulation of expanded ensembles using [OpenMM](http://openmm.org) and python with various met"
},
{
"path": "perses/__init__.py",
"chars": 235,
"preview": "#\nimport os\ndef get_datadir():\n \"\"\"Returns the data directory of this package\"\"\"\n return os.path.join(os.path.dirn"
},
{
"path": "perses/_version.py",
"chars": 18660,
"preview": "\n# This file helps to compute a version number in source trees obtained from\n# git-archive tarball (such as those provid"
},
{
"path": "perses/analysis/__init__.py",
"chars": 31,
"preview": "from perses.analysis import * \n"
},
{
"path": "perses/analysis/analyse_sams_convergence.py",
"chars": 1762,
"preview": "import matplotlib.pyplot as plt\nimport os\nimport sys\nfrom glob import glob\nfrom perses.analysis import utils\n\nif __name_"
},
{
"path": "perses/analysis/analysis.py",
"chars": 22954,
"preview": "\"\"\"\nAnalysis tools for perses automated molecular design.\n\nTODO\n----\n* Analyze all but last iteration to ensure we can a"
},
{
"path": "perses/analysis/analyze-profile.py",
"chars": 220,
"preview": "#!/usr/bin/env python\n\nimport pstats\np = pstats.Stats('profile.out')\np.strip_dirs().sort_stats(-1).print_stats()\n\nnrepor"
},
{
"path": "perses/analysis/cycles.py",
"chars": 4822,
"preview": "\"\"\"\nFunctions to plot free energy maps for sets of ligands\n\n\"\"\"\n\n__author__ = 'Hannah E. Bruce Macdonald'\n\n\nimport numpy"
},
{
"path": "perses/analysis/extract_trajectory.py",
"chars": 1648,
"preview": "\"\"\"\n\nFunctions to extract trajectory from a perses relative calculation\n\n\"\"\"\n\n\nimport numpy as np\nimport mdtraj as md\nfr"
},
{
"path": "perses/analysis/fah_analysis.py",
"chars": 10622,
"preview": "from cloudpathlib import AnyPath\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom openmmtools.multistat"
},
{
"path": "perses/analysis/generate-protonated-termini.py",
"chars": 1379,
"preview": "#!/bin/env python\n\n\"\"\"\nParse an AMBER OpenMM ffxml file to generate variants of amino acid residue templates with proton"
},
{
"path": "perses/analysis/load_simulations.py",
"chars": 10625,
"preview": "import logging\n_logger = logging.getLogger()\n_logger.setLevel(logging.INFO)\n_logger = logging.getLogger(\"load_simulation"
},
{
"path": "perses/analysis/resample.py",
"chars": 5656,
"preview": "import numpy as np\nfrom functools import wraps\nfrom itertools import islice\n\n\ndef samples_correlated(arrays, seed=None):"
},
{
"path": "perses/analysis/utils.py",
"chars": 2681,
"preview": "import numpy as np\nimport logging\n\n_logger = logging.getLogger(\"analysis/utils\")\n\ndef open_netcdf(filename):\n from ne"
},
{
"path": "perses/analysis/visualization.py",
"chars": 17584,
"preview": "\"\"\"\nVisualization tools for perses (protein mutations or small molecule transformations).\nRequires PDB and trajectory (."
},
{
"path": "perses/annihilation/__init__.py",
"chars": 2,
"preview": "#\n"
},
{
"path": "perses/annihilation/lambda_protocol.py",
"chars": 25858,
"preview": "from __future__ import print_function\nimport numpy as np\nimport logging\nimport copy\nfrom openmmtools.alchemy import Alch"
},
{
"path": "perses/annihilation/ncmc_switching.py",
"chars": 18913,
"preview": "from __future__ import print_function\nimport numpy as np\nimport copy\nimport logging\nfrom perses.dispersed.feptasks impor"
},
{
"path": "perses/annihilation/relative.py",
"chars": 270559,
"preview": "import simtk.openmm as openmm\nimport simtk.unit as unit\nimport mdtraj as md\nimport numpy as np\nimport copy\nimport enum\n\n"
},
{
"path": "perses/annihilation/rest.py",
"chars": 13190,
"preview": "\"\"\"\nFrom a standard simtk.openmm.system, make a REST2-amenable system\n\"\"\"\n\n\"\"\"\nImports\n\"\"\"\nimport simtk.openmm as openmm"
},
{
"path": "perses/app/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "perses/app/cli.py",
"chars": 6400,
"preview": "# New cli for testing\nimport logging\nimport os\nimport openmm.testInstallation\nfrom cloudpathlib import AnyPath\n\nimport c"
},
{
"path": "perses/app/fah_generator.py",
"chars": 35633,
"preview": "__author__ = 'dominic rufa'\n\n\"\"\"\nApplication API for setting up perses relative free energy calculations on Folding@Home"
},
{
"path": "perses/app/relative_hydration.py",
"chars": 5218,
"preview": "import simtk.openmm as openmm\nimport simtk.unit as unit\nfrom perses.annihilation.relative import HybridTopologyFactory\ni"
},
{
"path": "perses/app/relative_point_mutation_setup.py",
"chars": 44380,
"preview": "from __future__ import absolute_import\n\nfrom perses.utils.openeye import createOEMolFromSDF, extractPositionsFromOEMol\nf"
},
{
"path": "perses/app/relative_setup.py",
"chars": 135032,
"preview": "from __future__ import absolute_import\n\nfrom perses.dispersed import feptasks\nfrom perses.utils.openeye import createOEM"
},
{
"path": "perses/app/setup_relative_calculation.py",
"chars": 62104,
"preview": "import yaml\nimport numpy as np\nimport pickle\nimport os\nimport sys\nimport simtk.unit as unit\nimport logging\nimport warnin"
},
{
"path": "perses/bias/__init__.py",
"chars": 38,
"preview": "from perses.bias.bias_engine import *\n"
},
{
"path": "perses/bias/bias_engine.py",
"chars": 5401,
"preview": "\"\"\"\nThis is the base class for generating a biasing potential\nfor expanded ensemble simulation\n\"\"\"\nimport openmoltools\ni"
},
{
"path": "perses/data/181L.pdb",
"chars": 150417,
"preview": "HEADER HYDROLASE (O-GLYCOSYL) 19-APR-95 181L \nTITLE SPECIFICITY OF LIGAND BINDING"
},
{
"path": "perses/data/1sb0.pdb",
"chars": 3099384,
"preview": "HEADER TRANSCRIPTION 09-FEB-04 1SB0 \nTITLE SOLUTION STRUCTURE OF THE KIX"
},
{
"path": "perses/data/8mer-example/4zuh_peptide_capped.pdb",
"chars": 10584,
"preview": "REMARK 4 COMPLIES WITH FORMAT V. 3.0, 1-DEC-2006\nREMARK 888\nREMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODING"
},
{
"path": "perses/data/L99A-binders.txt",
"chars": 4830,
"preview": "(2-THIENYLTHIO)ACETONE\tCC(=O)CSc1cccs1\tSu AI, Lorber DM, Weston GS, Baase WA, Matthew BW, Shoichet BK, Proteins, 42, 279"
},
{
"path": "perses/data/L99A-non-binders.txt",
"chars": 5934,
"preview": "CYCLOHEXANE\tC1CCCCC1\tMorton A, Matthews, BW, Biochemistry, 34, 8576-88, (1995)\nTERT-BUTYLBENZENE\tCC(C)(C)c1ccccc1\tMorto"
},
{
"path": "perses/data/T4-inhibitors.xml",
"chars": 13805,
"preview": "<ForceField>\n <Info>\n <DateGenerated>2016-03-21</DateGenerated>\n </Info>\n <HarmonicAngleForce>\n <Angle type1=\"h1\" type"
},
{
"path": "perses/data/Tyk2_ligands_example/Tyk2_ligands_shifted.sdf",
"chars": 57319,
"preview": "ejm_31\n PyMOL2.3 3D 0\n\n 32 33 0 0 0 0 0 0 0 0999 V2000\n 35.4508 32.924"
},
{
"path": "perses/data/Tyk2_ligands_example/Tyk2_protein.pdb",
"chars": 378422,
"preview": "CRYST1 59.354 59.384 72.817 90.00 90.00 90.00 P 1 \nATOM 1 HH31 ACE 1 22.123 27.558 1"
},
{
"path": "perses/data/Tyk2_ligands_example/tyk2_0_3.yaml",
"chars": 2222,
"preview": "#provide the full path of the protein PDB file\nprotein_pdb: Tyk2_protein.pdb\n#provide the path to the ligand file with c"
},
{
"path": "perses/data/abl-imatinib/README.md",
"chars": 51,
"preview": "Abl:imatinib from one of Sonya's YANK calculations."
},
{
"path": "perses/data/abl-imatinib/complex.pdb",
"chars": 336200,
"preview": "ATOM 1 N ILE A 1 21.603 -4.697 24.226 1.00 0.00 N \nATOM 2 CA ILE A 1 21.164 "
},
{
"path": "perses/data/abl-imatinib/inhibitor.pdb",
"chars": 7151,
"preview": "HETATM 1 C1 MOL B 1 9.948 3.582 0.072 1.00 0.00 C \nHETATM 2 N1 MOL B 1 9.466 "
},
{
"path": "perses/data/abl-imatinib/receptor.pdb",
"chars": 345550,
"preview": "ATOM 1 N TRP A 1 -9.951 -18.473 -1.217 1.00 0.00 N \nATOM 2 CA TRP A 1 -8.582 "
},
{
"path": "perses/data/abl-src/abl-imatinib.pdb",
"chars": 336200,
"preview": "ATOM 1 N ILE A 1 21.603 -4.697 24.226 1.00 0.00 N \nATOM 2 CA ILE A 1 21.164 "
},
{
"path": "perses/data/abl-src/src-imatinib.pdb",
"chars": 338666,
"preview": "REMARK 1 PDBFIXER FROM: src-imatinib.pdb\nREMARK 1 CREATED WITH OPENMM 7.0, 2016-04-15\nATOM 1 N LEU A 1 "
},
{
"path": "perses/data/ala_vacuum.pdb",
"chars": 2150,
"preview": "REMARK 1 CREATED WITH OPENMM 7.4.1, 2020-03-01\nHETATM 1 H1 ACE 1 1 2.000 1.000 -0.000 1.00 0.00 "
},
{
"path": "perses/data/amber99sbildn-valence-only.xml",
"chars": 318024,
"preview": "<!-- Valence terms only -->\n<ForceField>\n <AtomTypes>\n <Type name=\"0\" class=\"N\" element=\"N\" mass=\"14.00672\"/>\n <Type n"
},
{
"path": "perses/data/amino_acid_templates/ALA.pdb",
"chars": 821,
"preview": "ATOM 1 N ALA 2 -0.677 -1.230 -0.491 1.00 0.00 N \nATOM 2 CA ALA 2 -0.001 "
},
{
"path": "perses/data/amino_acid_templates/ARG.pdb",
"chars": 1955,
"preview": "ATOM 1 N ARG 2 2.275 -5.251 4.946 1.00 0.00 N \nATOM 2 CA ARG 2 2.816 "
},
{
"path": "perses/data/amino_acid_templates/ASH.pdb",
"chars": 1064,
"preview": "ATOM 1 N ASH 2 28.512 45.560 9.232 1.00 0.00 N \nATOM 2 CA ASH 2 29.071 "
},
{
"path": "perses/data/amino_acid_templates/ASN.pdb",
"chars": 1145,
"preview": "ATOM 1 N ASN 2 2.507 -3.352 1.819 1.00 0.00 N \nATOM 2 CA ASN 2 3.091 "
},
{
"path": "perses/data/amino_acid_templates/ASP.pdb",
"chars": 983,
"preview": "ATOM 1 N ASP 2 1.687 -3.429 1.803 1.00 0.00 N \nATOM 2 CA ASP 2 2.246 "
},
{
"path": "perses/data/amino_acid_templates/CYS.pdb",
"chars": 902,
"preview": "ATOM 1 N CYS 2 1.634 -3.182 1.799 1.00 0.00 N \nATOM 2 CA CYS 2 2.193 "
},
{
"path": "perses/data/amino_acid_templates/GLH.pdb",
"chars": 1307,
"preview": "ATOM 1 N GLH 2 28.604 45.037 8.824 1.00 0.00 N \nATOM 2 CA GLH 2 29.163 "
},
{
"path": "perses/data/amino_acid_templates/GLN.pdb",
"chars": 1388,
"preview": "ATOM 1 N GLN 2 1.987 -4.086 1.046 1.00 0.00 N \nATOM 2 CA GLN 2 2.539 "
},
{
"path": "perses/data/amino_acid_templates/GLU.pdb",
"chars": 1226,
"preview": "ATOM 1 N GLU 2 1.780 -3.950 1.395 1.00 0.00 N \nATOM 2 CA GLU 2 2.339 "
},
{
"path": "perses/data/amino_acid_templates/GLY.pdb",
"chars": 561,
"preview": "ATOM 1 N GLY 22 1.103 -1.403 2.226 1.00 0.00 N\nATOM 2 CA GLY 22 2.528 -"
},
{
"path": "perses/data/amino_acid_templates/HID.pdb",
"chars": 1388,
"preview": "ATOM 1 N HID 2 29.627 44.998 8.697 1.00 0.00 N \nATOM 2 CA HID 2 30.173 "
},
{
"path": "perses/data/amino_acid_templates/HIE.pdb",
"chars": 1388,
"preview": "ATOM 1 N HIE 2 29.617 45.008 8.732 1.00 0.00 N \nATOM 2 CA HIE 2 30.171 "
},
{
"path": "perses/data/amino_acid_templates/HIP.pdb",
"chars": 1469,
"preview": "ATOM 1 N HIP 2 29.623 45.003 8.715 1.00 0.00 N \nATOM 2 CA HIP 2 30.177 "
},
{
"path": "perses/data/amino_acid_templates/HIS.pdb",
"chars": 1388,
"preview": "ATOM 1 N HIS 2 2.795 -3.976 1.305 1.00 0.00 N \nATOM 2 CA HIS 2 3.349 "
},
{
"path": "perses/data/amino_acid_templates/ILE.pdb",
"chars": 1550,
"preview": "ATOM 1 N ILE 2 2.691 -3.772 1.290 1.00 0.00 N \nATOM 2 CA ILE 2 3.188 "
},
{
"path": "perses/data/amino_acid_templates/LEU.pdb",
"chars": 1550,
"preview": "ATOM 1 N LEU 2 2.975 -3.732 1.538 1.00 0.00 N \nATOM 2 CA LEU 2 3.543 "
},
{
"path": "perses/data/amino_acid_templates/LYN.pdb",
"chars": 1712,
"preview": "ATOM 1 N LYN 2 28.674 43.813 8.197 1.00 0.00 N \nATOM 2 CA LYN 2 29.233 "
},
{
"path": "perses/data/amino_acid_templates/LYS.pdb",
"chars": 1793,
"preview": "ATOM 1 N LYS 2 1.849 -5.176 0.766 1.00 0.00 N \nATOM 2 CA LYS 2 2.408 "
},
{
"path": "perses/data/amino_acid_templates/MET.pdb",
"chars": 1388,
"preview": "ATOM 1 N MET 2 3.350 -3.541 1.267 1.00 0.00 N \nATOM 2 CA MET 2 3.838 "
},
{
"path": "perses/data/amino_acid_templates/PHE.pdb",
"chars": 1631,
"preview": "ATOM 1 N PHE 2 3.676 -3.399 1.389 1.00 0.00 N \nATOM 2 CA PHE 2 4.191 "
},
{
"path": "perses/data/amino_acid_templates/PRO.pdb",
"chars": 1145,
"preview": "ATOM 1 N PRO 2 2.946 -2.154 3.497 1.00 0.00 N \nATOM 2 CA PRO 2 3.456 "
},
{
"path": "perses/data/amino_acid_templates/SER.pdb",
"chars": 902,
"preview": "ATOM 1 N SER 2 1.677 -2.844 1.745 1.00 0.00 N \nATOM 2 CA SER 2 2.307 "
},
{
"path": "perses/data/amino_acid_templates/THR.pdb",
"chars": 1145,
"preview": "ATOM 1 N THR 2 1.776 -3.606 1.636 1.00 0.00 N \nATOM 2 CA THR 2 2.394 "
},
{
"path": "perses/data/amino_acid_templates/TRP.pdb",
"chars": 1955,
"preview": "ATOM 1 N TRP 2 3.928 -4.313 2.032 1.00 0.00 N \nATOM 2 CA TRP 2 4.490 "
},
{
"path": "perses/data/amino_acid_templates/TYR.pdb",
"chars": 1712,
"preview": "ATOM 1 N TYR 22 1.484 -3.803 3.856 1.00 0.00 N \nATOM 2 CA TYR 22 2.909 "
},
{
"path": "perses/data/amino_acid_templates/VAL.pdb",
"chars": 1307,
"preview": "ATOM 1 N VAL 2 2.208 -3.651 1.584 1.00 0.00 N \nATOM 2 CA VAL 2 2.729 "
},
{
"path": "perses/data/arg_solvated.cif",
"chars": 246193,
"preview": "data_cell\n# Created with OpenMM 7.7, 2022-04-08\n#\n_cell.length_a 29.6250\n_cell.length_b 29.6250\n_cell.leng"
},
{
"path": "perses/data/bace-example/Bace_ligands_shifted.sdf",
"chars": 157558,
"preview": "CAT-13f\n PyMOL2.3 3D 0\n\n 49 52 0 0 1 0 0 0 0 0999 V2000\n 30.5568 31.31"
},
{
"path": "perses/data/bace-example/Bace_protein.pdb",
"chars": 488987,
"preview": "CRYST1 70.419 72.124 66.012 90.00 90.00 90.00 P 1 \nATOM 1 N GLY 1 53.932 47.096 3"
},
{
"path": "perses/data/bace-example/TLA.sdf",
"chars": 1506,
"preview": "TLA\n PyMOL2.3 3D 0\n\n 14 13 0 0 0 0 0 0 0 0999 V2000\n 51.0480 41.7530 "
},
{
"path": "perses/data/bace-example/bace_setup.yaml",
"chars": 2029,
"preview": "#provide the full path of the protein PDB file\nprotein_pdb: Bace_protein.pdb\n\n#provide the path to the ligand file with "
},
{
"path": "perses/data/barstar-mutation/1brs_barnase_renumbered.pdb",
"chars": 174129,
"preview": "REMARK 1 CREATED WITH OPENMM 7.5, 2021-07-30\nCRYST1 207.250 43.860 84.710 90.00 107.76 90.00 P 1 1 \nH"
},
{
"path": "perses/data/barstar-mutation/1brs_barstar_renumbered.pdb",
"chars": 135897,
"preview": "REMARK 1 CREATED WITH OPENMM 7.5, 2021-07-30\nCRYST1 207.250 43.860 84.710 90.00 107.76 90.00 P 1 1 \nH"
},
{
"path": "perses/data/barstar-mutation/mmc2_barnase.pdb",
"chars": 140354,
"preview": "REMARK 1 CREATED WITH OPENMM 7.4.2, 2020-07-14\nCRYST1 207.250 43.860 84.710 90.00 107.76 90.00 P 1 1 "
},
{
"path": "perses/data/barstar-mutation/mmc2_barstar.pdb",
"chars": 117431,
"preview": "REMARK 1 CREATED WITH OPENMM 7.4.2, 2020-07-14\nCRYST1 207.250 43.860 84.710 90.00 107.76 90.00 P 1 1 "
},
{
"path": "perses/data/barstar-mutation/mutant.yaml",
"chars": 1971,
"preview": "# Specify the type of transformation\nsetup: protein\n\n# Specify the names of the project and run directories and which ph"
},
{
"path": "perses/data/cdk2-example/CDK2_fixed_nohet.pdb",
"chars": 729955,
"preview": "REMARK 1 PDBFIXER FROM: protein.pdb\nREMARK 1 CREATED WITH OPENMM 7.1.1, 2017-07-24\nATOM 1 N SER A 1 -1"
},
{
"path": "perses/data/cdk2-example/CDK2_ligands.sdf",
"chars": 59143,
"preview": "30\n 3D\n Structure written by MMmdl.\n 51 54 0 0 1 0 999 V2000\n 1.3901 29.1077 6"
},
{
"path": "perses/data/cdk2-example/CDK2_ligands_shifted.sdf",
"chars": 75974,
"preview": "30\n PyMOL2.3 3D 0\n\n 51 54 0 0 0 0 0 0 0 0999 V2000\n 49.7062 35.2933 "
},
{
"path": "perses/data/cdk2-example/CDK2_protein.pdb",
"chars": 938409,
"preview": "MODEL 1\nATOM 1 N SER 1 31.536 39.646 12.241 0.00 0.00 N \nATOM 5 CA SER "
},
{
"path": "perses/data/cdk2-example/README.md",
"chars": 1003,
"preview": "# CDK2 protein-ligand example\n\nThis folder contains an example setup for a protein-ligand relative free energy calculati"
},
{
"path": "perses/data/cdk2-example/cdk2-cache.json",
"chars": 13309,
"preview": "{\n \"_default\": {},\n \"gaff-2.11\": {\n \"1\": {\n \"ffxml\": \"<ForceField>\\n <Info>\\n <DateGenerated"
},
{
"path": "perses/data/cdk2-example/cdk2_setup_neq.yaml",
"chars": 2167,
"preview": "# Relative path to protein PDB file (with no missing heavy atoms)\nprotein_pdb: CDK2_fixed_nohet.pdb\n\n# Relative path to "
},
{
"path": "perses/data/cdk2-example/cdk2_setup_repex.yaml",
"chars": 2302,
"preview": "# Relative path to protein PDB file (with no missing heavy atoms)\nprotein_pdb: CDK2_fixed_nohet.pdb\n\n# Relative path to "
},
{
"path": "perses/data/clinical-kinase-inhibitors.csv",
"chars": 1958,
"preview": "Imatinib,C5=C(C1=CN=CC=C1)N=C(NC2=C(C=CC(=C2)NC(C3=CC=C(C=C3)CN4CCN(CC4)C)=O)C)N=C5\nDasatinib,C1=C(SC(=N1)NC2=CC(=NC(=N2"
},
{
"path": "perses/data/constant-pH/abl-imatinib/Imatinib-epik-charged.ffxml",
"chars": 34357,
"preview": "<ForceField>\n <Info>\n <DateGenerated>2016-05-27</DateGenerated>\n </Info>\n <Residues>\n <Residue name=\"imatinib-000\">\n "
},
{
"path": "perses/data/constant-pH/abl-imatinib/Imatinib-epik-charged.mol2",
"chars": 35462,
"preview": "@<TRIPOS>MOLECULE\n4-[(4-methylpiperazin-1-ium-1-yl)methyl]-~{N}-[4-methyl-3-[[4-(3-pyridyl)pyrimidin-2-yl]amino]phenyl]b"
},
{
"path": "perses/data/constant-pH/abl-imatinib/Imatinib-state-penalties.out",
"chars": 85,
"preview": " 0.31570000\n 0.57260000\n 2.03060000\n 5.43010000\n 5.68700000\n"
},
{
"path": "perses/data/constant-pH/abl-imatinib/README.md",
"chars": 543,
"preview": "Abl:imatinib from one of Sonya's YANK calculations.\n\n## Manifest\n* `receptor.pdb` - Abl\n* `inhibitor.pdb` - imatinib\n* `"
},
{
"path": "perses/data/constant-pH/abl-imatinib/complex.pdb",
"chars": 336200,
"preview": "ATOM 1 N ILE A 1 21.603 -4.697 24.226 1.00 0.00 N \nATOM 2 CA ILE A 1 21.164 "
},
{
"path": "perses/data/constant-pH/abl-imatinib/generate-ligand-ffxml.py",
"chars": 844,
"preview": "#!/usr/bin/env python\n\"\"\"\nGenerate ffxml files for ligands in a multi-mole mol2.\n\"\"\"\n\n\nmol2_filename = 'Imatinib-epik-ch"
},
{
"path": "perses/data/constant-pH/abl-imatinib/inhibitor.pdb",
"chars": 7151,
"preview": "HETATM 1 C1 MOL B 1 9.948 3.582 0.072 1.00 0.00 C \nHETATM 2 N1 MOL B 1 9.466 "
},
{
"path": "perses/data/constant-pH/abl-imatinib/receptor.pdb",
"chars": 345550,
"preview": "ATOM 1 N TRP A 1 -9.951 -18.473 -1.217 1.00 0.00 N \nATOM 2 CA TRP A 1 -8.582 "
},
{
"path": "perses/data/constant-pH/imidazole/README.md",
"chars": 156,
"preview": "# imidazole test data for protonation state sampling\n\n## Manifest\n* `generate-protomers-from-smiles.py` - script to gene"
},
{
"path": "perses/data/constant-pH/imidazole/convert.py",
"chars": 300,
"preview": "#!/usr/bin/env python\nfrom openeye.oechem import OEGraphMol, OEReadMolecule, OEWriteMolecule, oemolistream, oemolostream"
},
{
"path": "perses/data/constant-pH/imidazole/generate-protomers-from-smiles.py",
"chars": 9111,
"preview": "#!/usr/bin/env python\n\n\"\"\"\nGenerate protomers using Epik.\n\n\"\"\"\nfrom __future__ import print_function\nimport os\nimport re"
},
{
"path": "perses/data/constant-pH/imidazole/imidazole/imidazole-epik-charged.mol2",
"chars": 2218,
"preview": "@<TRIPOS>MOLECULE\nimidazole\n 9 9 1 0 0\nSMALL\nUSER_CHARGES\n\n@<TRIPOS>ATOM\n 1 C1 0.6549 "
},
{
"path": "perses/data/constant-pH/imidazole/imidazole/imidazole-epik-charged.pdb",
"chars": 1630,
"preview": "COMPND imidazole\nATOM 0 C1 IMI 1 0.655 -0.778 -0.364 1.00 20.00 C\nATOM 0 C2 IMI "
},
{
"path": "perses/data/constant-pH/imidazole/imidazole/imidazole-epik.mae",
"chars": 3994,
"preview": "{ \n s_m_m2io_version\n :::\n 2.0.0 \n} \n\nf_m_ct { \n s_m_title\n s_m_source_file\n i_m_source_file_index\n r_lp_tautomer_probab"
},
{
"path": "perses/data/constant-pH/imidazole/imidazole/imidazole-epik.mol2",
"chars": 2292,
"preview": "@<TRIPOS>MOLECULE\nimidazole\n9 9 1\nSMALL\nUSER_CHARGES\n\n\n@<TRIPOS>ATOM\n 1 C1 0.6549 -0.7784 -0.3640"
},
{
"path": "perses/data/constant-pH/imidazole/imidazole/imidazole-epik.sdf",
"chars": 2385,
"preview": "imidazole\n 3D\n Structure written by MMmdl.\n 9 9 0 0 1 0 999 V2000\n 0.6549 -0.77"
},
{
"path": "perses/data/constant-pH/imidazole/imidazole/imidazole-input.mol2",
"chars": 1041,
"preview": "@<TRIPOS>MOLECULE\nimidazole\n 9 9 1 0 0\nSMALL\nUSER_CHARGES\n\n@<TRIPOS>ATOM\n 1 C1 0.6549 "
},
{
"path": "perses/data/constant-pH/imidazole/imidazole/imidazole-state-penalties.out",
"chars": 34,
"preview": " 0.09100000\n 1.15520000\n"
},
{
"path": "perses/data/constant-pH/imidazole/imidazole.pdb",
"chars": 960,
"preview": "COMPND imidazole\nHETATM 1 C1 UNL 1 0.655 -0.778 -0.364 1.00 20.00 C\nHETATM 2 C2 UNL "
},
{
"path": "perses/data/constrained-to-unconstrained/ligands_constraint_test.sdf",
"chars": 7087,
"preview": "ligand0001\n 3D\n Schrodinger Suite 2021-1.\n 52 55 0 0 1 0 999 V2000\n 15.3086 7.809"
},
{
"path": "perses/data/gaff-valence-only.xml",
"chars": 462637,
"preview": "<ForceField>\n <Info>\n <DateGenerated>2017-02-17</DateGenerated>\n <Reference>gaff with only valence terms</Reference>\n "
}
]
// ... and 91 more files (download for full content)
About this extraction
This page contains the full source code of the choderalab/perses GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 291 files (64.6 MB), approximately 11.6M tokens, and a symbol index with 1088 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.