Skip to content

Commit

Permalink
Merge branch 'master' into high-throughput
Browse files Browse the repository at this point in the history
  • Loading branch information
nbruciaferri committed Jul 15, 2024
2 parents f515287 + c68ce3d commit 218fd2c
Show file tree
Hide file tree
Showing 16 changed files with 547 additions and 512 deletions.
4 changes: 2 additions & 2 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "miniconda3-4.7"
python: "mambaforge-latest"
# You can also specify other tool versions:
# nodejs: "19"
# rust: "1.64"
Expand All @@ -20,7 +20,7 @@ sphinx:
configuration: docs/source/conf.py

conda:
environment: cosolvkit_env.yml
environment: docs/source/environment.yml

# Optionally build your docs in additional formats such as PDF and ePub
# formats:
Expand Down
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include README.md
include LICENSE
include docs/*
include example/*
include cosolvkit/data/*
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
[![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/) [![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL_v2.1-green.svg)](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html) [![PyPI - Version](https://img.shields.io/pypi/v/cosolvkit)](https://pypi.org/project/cosolvkit/0.4.1/) [![Powered by RDKit](https://img.shields.io/badge/Powered%20by-RDKit-3838ff.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAFVBMVEXc3NwUFP8UPP9kZP+MjP+0tP////9ZXZotAAAAAXRSTlMAQObYZgAAAAFiS0dEBmFmuH0AAAAHdElNRQfmAwsPGi+MyC9RAAAAQElEQVQI12NgQABGQUEBMENISUkRLKBsbGwEEhIyBgJFsICLC0iIUdnExcUZwnANQWfApKCK4doRBsKtQFgKAQC5Ww1JEHSEkAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wMy0xMVQxNToyNjo0NyswMDowMDzr2J4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDMtMTFUMTU6MjY6NDcrMDA6MDBNtmAiAAAAAElFTkSuQmCC)](https://www.rdkit.org/)
[![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/)
[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL_v2.1-green.svg)](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
[![Documentation Status](https://readthedocs.org/projects/cosolvkit/badge/?version=latest)](https://cosolvkit.readthedocs.io/en/latest/?badge=latest)
![Conda Version](https://img.shields.io/conda/vn/conda-forge/cosolvkit)
![Conda Platform](https://img.shields.io/conda/pn/conda-forge/cosolvkit)
![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/cosolvkit)
[![PyPI - Version](https://img.shields.io/pypi/v/cosolvkit)](https://pypi.org/project/cosolvkit/0.4.7/)
[![Powered by RDKit](https://img.shields.io/badge/Powered%20by-RDKit-3838ff.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAFVBMVEXc3NwUFP8UPP9kZP+MjP+0tP////9ZXZotAAAAAXRSTlMAQObYZgAAAAFiS0dEBmFmuH0AAAAHdElNRQfmAwsPGi+MyC9RAAAAQElEQVQI12NgQABGQUEBMENISUkRLKBsbGwEEhIyBgJFsICLC0iIUdnExcUZwnANQWfApKCK4doRBsKtQFgKAQC5Ww1JEHSEkAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wMy0xMVQxNToyNjo0NyswMDowMDzr2J4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDMtMTFUMTU6MjY6NDcrMDA6MDBNtmAiAAAAAElFTkSuQmCC)](https://www.rdkit.org/)



Expand All @@ -12,20 +18,27 @@ Pre-print version of the original paper is freely accessible at the link https:/
The installation instructions, documentation and tutorials can be found on http://cosolvkit.readthedocs.io/.

## Installation
I highly recommend you to install the Anaconda distribution (https://www.continuum.io/downloads) if you want a clean python environnment with nearly all the prerequisites already installed. To install everything properly, you just have to do this:
`Cosolvkit` package is available via `conda` and can be installed:
```bash
$ conda create -n cosolvkit -c conda-forge -f cosolvkit_env.yml
$ conda install --channel conda-forge::cosolvkit
```

or via `mamba`:
```bash
$ mamba install -c conda-forge cosolvkit
```
For faster installation, use `mamba` or `micromamba` instead of `conda`.

Finally, we can install the `CosolvKit` package via `pip`:
```bash
$ pip instal cosolvkit
```

or directly download and install the source code from git:
I highly recommend you to install the Anaconda distribution (https://www.continuum.io/downloads) if you want a clean python environnment with nearly all the prerequisites already installed. To install everything properly, you just have to do this (for faster installation, use `mamba` or `micromamba` instead of `conda`):

```bash
$ conda create -n cosolvkit -c conda-forge -f environment.yml

$ git clone https://github.com/forlilab/cosolvkit
$ cd cosolvkit
$ pip install -e .
Expand Down
Empty file added cosolvkit/cli/__init__.py
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def cmd_lineparser():

return parser.parse_args()

if __name__ == "__main__":
def main():
args = cmd_lineparser()
config_file = args.config
config = Config.from_config(config_file)
Expand Down Expand Up @@ -174,3 +174,8 @@ def cmd_lineparser():
seed=None
)
print(f"Simulation finished after {(time.time() - start)/60:.2f} min.")
return


if __name__ == "__main__":
sys.exit(main())
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
import argparse
from cosolvkit.analysis import Report

Expand All @@ -17,8 +18,7 @@ def cmd_lineparser():
action='store', help='path to the json file containing cosolvents used for the simulation')
return parser.parse_args()


if __name__ == "__main__":
def main():
args = cmd_lineparser()
log_file = args.log_file
traj_file = args.traj_file
Expand All @@ -33,4 +33,9 @@ def cmd_lineparser():
report.trajectory,
density_files=densities,
selection_string='',
out_path=out_path)
out_path=out_path)
return


if __name__ == "__main__":
sys.exit(main())
37 changes: 19 additions & 18 deletions cosolvkit/cosolvent_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
import io
from collections import defaultdict
from typing import Union, Tuple
import numpy as np
from scipy import spatial
from scipy.stats import qmc
Expand Down Expand Up @@ -673,11 +674,11 @@ def add_cosolvents(self,
:param cosolvents: keys are cosolvent molecules and values are 3D coordinates of the molecule
:type cosolvents: dict
:param vectors: vectors defining the simulation box
:type vectors: tuple[openmm.Vec3, openmm.Vec3, openmm.Vec3]
:type vectors: Tuple[openmm.Vec3, openmm.Vec3, openmm.Vec3]
:param lowerBound: lower bound of the simulation box
:type lowerBound: openmm.unit.Quantity | Vec3
:type lowerBound: Union[openmm.unit.Quantity, Vec3]
:param upperBound: upper bound of the simulation box
:type upperBound: openmm.unit.Quantity | Vec3
:type upperBound: [openmm.unit.Quantity, Vec3]
:param receptor_positions: list of 3D coordinates of the receptor
:type receptor_positions: list
:param max_attempts_per_mol: the maximum number of times we attempt to insert a single molecule
Expand Down Expand Up @@ -932,15 +933,15 @@ def accept_reject(self,
:param valid_ids: valid halton indices
:type valid_ids: list
:param lowerBound: lower bound of the box
:type lowerBound: openmm.unit.Quantity | Vec3
:type lowerBound: Union[openmm.unit.Quantity, Vec3]
:param upperBound: upper bound of the box
:type upperBound: openmm.unit.Quantity | Vec3
:type upperBound: Union[openmm.unit.Quantity, Vec3]
:param protein_kdtree: tree of the protein's positions
:type protein_kdtree: spatial.cKDTree
:param max_num_trials: the maximum number of halton moves to make
:param max_num_trials: int
:return: accepted coordinates for the cosolvent and the used halton ids
:rtype: tuple[np.ndarray, list]
:rtype: Tuple[np.ndarray, list]
"""
num_trials = 0
accepted = False
Expand Down Expand Up @@ -970,16 +971,16 @@ def accept_reject(self,

def is_in_box(self,
xyzs: np.ndarray,
lowerBound: openmmunit.Quantity | Vec3,
upperBound: openmmunit.Quantity | Vec3) -> bool:
lowerBound: Union[openmmunit.Quantity, Vec3],
upperBound: Union[openmmunit.Quantity, Vec3]) -> bool:
"""Checks if the coordinates are in the box or not
:param xyzs: coordinates to check
:type xyzs: np.ndarray
:param lowerBound: lower bound of the box
:type lowerBound: openmmunit.Quantity | Vec3
:type lowerBound: Union[openmmunit.Quantity, Vec3]
:param upperBound: upper bound of the box
:type upperBound: openmmunit.Quantity | Vec3
:type upperBound: Union[openmmunit.Quantity, Vec3]
:return: True if all the coordinates are in the box, Flase otherwise
:rtype: bool
"""
Expand Down Expand Up @@ -1060,13 +1061,13 @@ def calculate_mol_volume(self, mol_positions: np.ndarray) -> float:
points = np.unique(np.hstack(query)).astype(int)
return round(len(points)*mesh_step**3, 2)

def fitting_checks(self) -> float | None:
def fitting_checks(self) -> Union[float, None]:
"""Checks if the required cosolvents can fit in the box and
do not exceed the 50% of the available fillable volume
(volume not occupied by the receptor, if present).
:return: available volume if the cosolvents can fit, None otherwise
:rtype: float | None
:rtype: Union[float, None]
"""
prot_volume = 0
if self.receptor:
Expand All @@ -1086,11 +1087,11 @@ def fitting_checks(self) -> float | None:
return None
return empty_available_volume

def liters_to_cubic_nanometers(self, liters: float | openmmunit.Quantity) -> float:
def liters_to_cubic_nanometers(self, liters: Union[float, openmmunit.Quantity]) -> float:
"""Converts liters in cubic nanometers
:param liters: volume to convert
:type liters: float | openmm.unit.Quantity
:type liters: Union[float, openmm.unit.Quantity]
:return: converted volume
:rtype: float
"""
Expand Down Expand Up @@ -1162,10 +1163,10 @@ def _parametrize_cosolvents(self, cosolvents: dict, small_molecule_ff="espaloma"
def _build_box(self,
positions: np.ndarray,
padding: openmmunit.Quantity,
radius: openmmunit.Quantity = None) -> tuple[tuple[Vec3, Vec3, Vec3],
radius: openmmunit.Quantity = None) -> Tuple[Tuple[Vec3, Vec3, Vec3],
Vec3,
openmmunit.Quantity | Vec3,
openmmunit.Quantity | Vec3]:
Union[openmmunit.Quantity, Vec3],
Union[openmmunit.Quantity, Vec3]]:
"""Builds the simulation box. If a receptor is passed it is used alongside with the padding
parameter to build the box automatically, otherwise a radius has to be passed. If no receptor
the box is centered on the point [0, 0, 0].
Expand All @@ -1179,7 +1180,7 @@ def _build_box(self,
:return: The first element returned is a tuple containing the three vectors describing the simulation box.
The second element is the box itself.
Third and fourth elements are the lower and upper bound of the simulation box.
:rtype: tuple[tuple[Vec3, Vec3, Vec3], Vec3, openmmunit.Quantity | Vec3, openmmunit.Quantity | Vec3]
:rtype: tuple[tuple[Vec3, Vec3, Vec3], Vec3, Union[openmmunit.Quantity, Vec3], Union[openmmunit.Quantity, Vec3]]
"""
padding = padding.value_in_unit(openmmunit.nanometer)
if positions is not None:
Expand Down
8 changes: 4 additions & 4 deletions cosolvkit/data/config.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"cosolvents": "data/cosolvents.json",
"forcefields": "data/forcefields.json",
"cosolvents": "cosolvkit/data/cosolvents.json",
"forcefields": "cosolvkit/data/forcefields.json",
"md_format": "openmm",
"receptor": true,
"protein_path": "/path/to/protein/structure",
"protein_path": "example/protein.pdb",
"clean_protein": true,
"keep_heterogens": false,
"variants_d": {},
Expand All @@ -19,7 +19,7 @@
"cosolvent_placement": 0,
"waters_to_keep": [],
"radius": null,
"output": "/path/to/where/to/save/results",
"output": "results",
"run_cosolvent_system": true,
"run_md": false
}
5 changes: 3 additions & 2 deletions cosolvkit/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import shutil
import subprocess
import importlib
from typing import List, Tuple
from collections import defaultdict

import numpy as np
Expand Down Expand Up @@ -89,7 +90,7 @@ class MutuallyExclusiveParametersError(Exception):

# simulation.context.setParameter('k', k)

def fix_pdb(pdbfile: str, pdbxfile: str, keep_heterogens: bool=False) -> tuple[Topology, list]:
def fix_pdb(pdbfile: str, pdbxfile: str, keep_heterogens: bool=False) -> Tuple[Topology, List]:
"""Fixes common problems in PDB such as:
- missing atoms
- missing residues
Expand Down Expand Up @@ -123,7 +124,7 @@ def fix_pdb(pdbfile: str, pdbxfile: str, keep_heterogens: bool=False) -> tuple[T
fixer.addMissingHydrogens(7)
return fixer.topology, fixer.positions

def add_variants(topology: Topology, positions: list, variants: list=list()) -> tuple[Topology, list]:
def add_variants(topology: Topology, positions: list, variants: list=list()) -> Tuple[Topology, List]:
"""Adds variants for specific protonation states.
:param topology: openmm topology
Expand Down
Loading

0 comments on commit 218fd2c

Please sign in to comment.