Skip to content

Commit

Permalink
documentation update
Browse files Browse the repository at this point in the history
  • Loading branch information
tkpiskorz committed Jun 11, 2024
1 parent 53a9331 commit b369821
Show file tree
Hide file tree
Showing 17 changed files with 125 additions and 111 deletions.
9 changes: 9 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
The MIT License (MIT)

Copyright (c) 2024

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.
58 changes: 0 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,6 @@ Metallicious (a playful combination of "metal" and "delicious") is an automated

Metallicious works with minimal user input, relying heavily on educated guesses, which may not always yield the expected results. Therefore, it is recommended to use the tool with caution.

## Requirements:
- [rdkit](https://www.rdkit.org/)
- [networkx](https://networkx.org/)
- [MDAnalysis](https://www.mdanalysis.org/)
- [ParmEd](https://parmed.github.io/ParmEd/html/index.html)

(**Optional**) the parametrization of templates requires:
- [autode](https://github.com/duartegroup/autodE)
- [ORCA](https://orcaforum.kofo.mpg.de/app.php/portal)
- [psiRESP](https://github.com/lilyminium/psiresp)

(**Optional**) simple force-field parametrization with General Amber Force-field (GAFF) requires:
- [ambertools](https://ambermd.org/AmberTools.php)

**Limitations**: The code currently supports organometallic structures with metals separated by at least 2 non-metal atoms. Metal clusters are not supported. Additionally, metals of the same type must have the same charge and multiplicity.

## Installation:
```
conda install rdkit autode psiresp mdanalysis networkx qcelemental==0.25.1 ambertools --channel conda-forge
Expand All @@ -49,48 +33,6 @@ cage.parametrize(out_coord='out.pdb', out_topol='out.top')
```
The `supramolecular_structure` function takes a coordination file (*.xyz, *.pdb, *.gro, etc. supported by MDAnalysis), topology file (*top, *prmtop, supported by ParmEd), dictionary of metal ions along with their charge (and in case template parametrization is needed multiplicity) and type of Van der Waals metal parameters as input.

## Initial topology file
If you don't have a topology file, you can generate a simple force-field parametrization using General Amber Force-field (GAFF):

```
from metallicious import supramolecular_structure
cage = supramolecular_structure('ru_pd.xyz', metal_charges={'Ru': 2, 'Pd':2 }, vdw_type='uff')
cage.prepare_initial_topology()
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
```
However, we do not intend to automate the parametrization of the organic part of the molecule.
Please refer to specialized tools such as gromacs, atb, ambertools, and charmm-gui.


# Handling missing templates

The number of combination of possible ligands and metal results that inevitibly you will encounter metal site for which there is no template.
In such cases to solutions are possible:

### 1. Parametrize template
We recommend to run template parametrization on HPC/cluster as it can take some time (our experience is ~8h on 8 CPUs per template).

Specifying explicitly the metal multiplicity using the metal_charge_mult variable instead of metal_charges, will automatically inform metallicious to be ready to parametrize the template

```
from metallicious import supramolecular_structure
cage = supramolecular_structure('ru_pd.xyz', metal_charge_mult = {'Ru': (2,1), 'Pd':(2,1)}, vdw_type='uff')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
```

### 2. Truncate existing template

If an exact template is unavailable in the library, you can truncate part of an existing template.
Truncation is based on the distance from the metal centre, such as 4-bonds away ("dihedral"), 3-bonds away ("angles"), or 1-bond away ("bonds").
Such a strategy is fast but results in a loss of accuracy.

For example:
```
from metallicious import supramolecular_structure
cage = supramolecular_structure('ru_pd.xyz', metal_charge_mult = {'Ru': (2,1), 'Pd':(2,1)}, truncation_scheme = 'dihedral')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
```

## Command line
It is also possible to use the metallicious just form command line. For example:
```
Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Welcome to metallicious's documentation!
:alt: Figure of summary of metallicious protocol



**Limitations**: The code currently supports organometallic structures with metals separated by at least 2 non-metal atoms. Metal clusters are not supported. Additionally, metals of the same type must have the same charge and multiplicity.

.. note::

Expand Down
2 changes: 0 additions & 2 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
Installation
=====

.. _installation:

Expand Down
111 changes: 88 additions & 23 deletions docs/source/usage.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Usage
=====


.. _usage:

Expand Down Expand Up @@ -83,25 +82,92 @@ For example:
cage = supramolecular_structure('ru_pd.xyz', metal_charge_mult = {'Ru': (2,1), 'Pd':(2,1)}, truncation_scheme = 'dihedral')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
The extended list of supramolecular_structure class:

:param filename: (str) name of the coordination file
:param metal_charge_mult: (dict) the names charges, and multiplicity of the metals in format
{metal_name: (metal_charges, multiplicity)}
:param metal_charges: (dict) the names and charges of metals in the input structure in format:
{metal_name1: metal_charges1, metal1_name2: metal_charge2}
:param vdw_type: (str) name of LJ dataset used for metal paramters
:param topol: (str) path to topology (optional)
:param keywords: list(str) the keywords for QM calculations
:param improper_metal: (bool) if True it will parametrize the improper dihedral involving metal
:param donors: (list(str)) list of atom elements with which metal forms bond
:param library_path: (str) directory of template library, be default where the script is
:param ff: (str) parametrization protocol for small organic molecules (only gaff available)
:param search_library: (bool) if True, metallicious searrched templates in template library,
if False, it will parametrize template
:param fingerprint_guess_list: (list(str)) list of templates to check
:param truncation_scheme: (str) name of the truncation scheme
:param covalent_cutoff: (float) if metal-atoms smaller then cutoff it creates bonds ligand with metal
Input for supramolecular_structure class
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The extended input list of supramolecular_structure class:

.. list-table::
:header-rows: 1

* - Variable
- Type
- Description
- Default
- Needs to be specified?
* - filename
- str
- name of the coordination file
- None
- Yes
* - metal_charge_mult
- dict
- the names charges, and multiplicity of the metals in format {metal_name: (metal_charges, multiplicity)}
- None
- Yes or metal_charges
* - metal_charges
- dict
- the names and charges of metals in the input structure in format: {metal_name1: metal_charges1, metal1_name2: metal_charge2}
- None
- Yes or metal_charge_mult
* - LJ_type
- str
- name of LJ dataset used for metal paramters (uff, merz-tip3p, merz-opc3, merz-spc/e, merz-tip3p-fb, merz-opc, merz-tip4p-fb, merz-tip4-ew, zhang-tip3p, zhang-opc3, zhang-spc/e, zhang-spc/eb, zhang-tip3p-fb, zhang-opc, zhang-tip4p/2005, zhang-tip4p-d, zhang-tip4p-fb, zhang-tip4p-ew)
- None
- Yes
* - topol
- str
- force-field parameters file
- None
- Yes, unless later prepare_initial_topol used
* - keywords
- list(str)
- autodE keywords for QM calculations
- PBE0 D3BJ def2-SVP tightOPT freq
- No
* - improper_metal
- bool
- if True it will parametrize the improper dihedral involving metal
- False
- No
* - donors
- list(str)
- list of atom elements with which metal forms bond
- ['N', 'S', 'O']
- No
* - library_path
- str
- directory of template library, be default where the script is
- path to metallicious + /library
- No
* - search_library
- bool
- if True, metallicious searches templates in template library,if False, it will parametrize template
- True
- No
* - ff
- str
- parametrization protocol for small organic molecules (only gaff available at the moment)
- 'gaff'
- No
* - fingerprint_guess_list
- list(str)
- list of template names, which will be checked from library
- None
- No
* - truncation_scheme
- str
- name of the truncation scheme
- None
- No
* - covalent_cutoff
- float
- if metal-atoms smaller then cutoff it is assumed that creates bond with the metal
- 3.0
- No



Bash command line
Expand Down Expand Up @@ -166,8 +232,7 @@ Extended list of the bash command:
- No
* - -LJ_type
- Type of parameters for Lennard-Jones parameters
- .. | Wrapped text
uff, merz-tip3p, merz-opc3, merz-spc/e, merz-tip3p-fb, merz-opc, merz-tip4p-fb, merz-tip4-ew, zhang-tip3p, zhang-opc3, zhang-spc/e, zhang-spc/eb, zhang-tip3p-fb, zhang-opc, zhang-tip4p/2005, zhang-tip4p-d, zhang-tip4p-fb, zhang-tip4p-ew
- uff, merz-tip3p, merz-opc3, merz-spc/e, merz-tip3p-fb, merz-opc, merz-tip4p-fb, merz-tip4-ew, zhang-tip3p, zhang-opc3, zhang-spc/e, zhang-spc/eb, zhang-tip3p-fb, zhang-opc, zhang-tip4p/2005, zhang-tip4p-d, zhang-tip4p-fb, zhang-tip4p-ew
- uff
- No
* - -truncate
Expand Down
2 changes: 1 addition & 1 deletion metallicious/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def main():
truncation_scheme = args.truncate

cage = supramolecular_structure(filename=filename, metal_charge_mult=metal_charge_mult,
metal_charges=metal_charges, vdw_type=vdw_type, topol=topol, keywords=keywords,
metal_charges=metal_charges, LJ_type=vdw_type, topol=topol, keywords=keywords,
improper_metal=improper_metal, donors=donors,
truncation_scheme=truncation_scheme)

Expand Down
2 changes: 1 addition & 1 deletion metallicious/examples/example1_quick_start/example1.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
'''

from metallicious import supramolecular_structure
cage = supramolecular_structure('ru_pd.pdb', metal_charges={'Ru': 2, 'Pd':2 }, topol='ru_pd.top', vdw_type='uff')
cage = supramolecular_structure('ru_pd.pdb', metal_charges={'Ru': 2, 'Pd':2 }, topol='ru_pd.top', LJ_type='uff')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
2 changes: 1 addition & 1 deletion metallicious/examples/example2_no_topology/example2.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
'''

from metallicious import supramolecular_structure
cage = supramolecular_structure('ru_pd.xyz', metal_charges={'Ru': 2, 'Pd':2 }, vdw_type='uff')
cage = supramolecular_structure('ru_pd.xyz', metal_charges={'Ru': 2, 'Pd':2 }, LJ_type='uff')
cage.prepare_initial_topology()
cage.parametrize(out_coord='out.pdb', out_topol='out.top')

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
'''

from metallicious import supramolecular_structure
cage = supramolecular_structure('ru_pd.xyz', metal_charges={'Ru': 2, 'Pd':2 }, vdw_type='uff')
cage = supramolecular_structure('ru_pd.xyz', metal_charges={'Ru': 2, 'Pd':2 }, LJ_type='uff')
cage.prepare_initial_topology(homoleptic_ligand_topol='linker.top')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
# This will not work becasue there is no exact template for this site:
# cage = supramolecular_structure('cage.pdb', topol='topol.top', metal_charges={'Pd':2 }, vdw_type='merz-opc')

cage = supramolecular_structure('cage.pdb', topol='topol.top', metal_charges={'Pd':2 }, vdw_type='merz-opc', truncation_scheme='dihedral')
cage = supramolecular_structure('cage.pdb', topol='topol.top', metal_charges={'Pd':2 }, LJ_type='merz-opc', truncation_scheme='dihedral')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')

2 changes: 1 addition & 1 deletion metallicious/examples/example5_protein/example5.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
'''

from metallicious import supramolecular_structure
cage = supramolecular_structure('protein.gro', metal_charges={'Zn': 2}, topol='protein.top', vdw_type='merz-opc')
cage = supramolecular_structure('protein.gro', metal_charges={'Zn': 2}, topol='protein.top', LJ_type='merz-opc')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
# This will not work becasue there is no exact template for this site:
# cage = supramolecular_structure('cage.pdb', topol='topol.top', metal_charges={'Pd':2 }, vdw_type='merz-opc')

cage = supramolecular_structure('cage.pdb', topol='topol.top', metal_charges={'Pd':2 }, vdw_type='merz-opc', truncation_scheme='dihedral')
cage = supramolecular_structure('cage.pdb', topol='topol.top', metal_charges={'Pd':2 }, LJ_type='merz-opc', truncation_scheme='dihedral')
cage.parametrize(out_coord='out.pdb', out_topol='out.top')

2 changes: 1 addition & 1 deletion metallicious/examples/example6_mof/example6.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
'''

from metallicious import supramolecular_structure
cage = supramolecular_structure('Co_mof.pdb', metal_charges={'Co':2}, vdw_type='merz-opc')
cage = supramolecular_structure('Co_mof.pdb', metal_charges={'Co':2}, LJ_type='merz-opc')
cage.prepare_initial_topology()
cage.parametrize(out_coord='out.pdb', out_topol='out.top')
30 changes: 15 additions & 15 deletions metallicious/parametrize_new_sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class supramolecular_structure:
The main structure holidng all the information about the intput and communicating between different classes
'''
def __init__(self, filename, metal_charge_mult=None, metal_charges=None, vdw_type=None, topol=None,
def __init__(self, filename, metal_charge_mult=None, metal_charges=None, LJ_type=None, topol=None,
keywords=['PBE0', 'D3BJ', 'def2-SVP', 'tightOPT', 'freq'], improper_metal=False,
donors=['N', 'S', 'O'],
library_path=f'{os.path.dirname(__file__):s}/library/', ff='gaff', search_library=True,
Expand All @@ -36,14 +36,14 @@ def __init__(self, filename, metal_charge_mult=None, metal_charges=None, vdw_typ
{metal_name: (metal_charges, multiplicity)}
:param metal_charges: (dict) the names and charges of metals in the input structure in format:
{metal_name1: metal_charges1, metal1_name2: metal_charge2}
:param vdw_type: (str) name of LJ dataset used for metal paramters
:param LJ_type: (str) name of LJ dataset used for metal paramters
:param topol: (str) path to topology (optional)
:param keywords: list(str) the keywords for QM calculations
:param improper_metal: (bool) if True it will parametrize the improper dihedral involving metal
:param donors: (list(str)) list of atom elements with which metal forms bond
:param library_path: (str) directory of template library, be default where the script is
:param ff: (str) parametrization protocol for small organic molecules (only gaff available)
:param search_library: (bool) if True, metallicious searrched templates in template library,
:param search_library: (bool) if True, metallicious searches templates in template library,
if False, it will parametrize template
:param fingerprint_guess_list: (list(str)) list of templates to check
:param truncation_scheme: (str) name of the truncation scheme
Expand Down Expand Up @@ -89,29 +89,29 @@ def __init__(self, filename, metal_charge_mult=None, metal_charges=None, vdw_typ
else:
raise ValueError("Not correct format of metal_charge_mult/metal_charges")

if vdw_type == 'custom' and topol is not None:
if LJ_type == 'custom' and topol is not None:
self.vdw_type = 'custom'

elif vdw_type is None:
for vdw_type in vdw_data:
elif LJ_type is None:
for LJ_type in vdw_data:

present = [(metal_name in vdw_data[vdw_type] or f"{metal_name:}{self.metal_charge_dict[metal_name]:}" in vdw_data[vdw_type]) for metal_name in self.metal_names]
present = [(metal_name in vdw_data[LJ_type] or f"{metal_name:}{self.metal_charge_dict[metal_name]:}" in vdw_data[LJ_type]) for metal_name in self.metal_names]
if sum(present) == len(present):
self.vdw_type = vdw_type
self.vdw_type = LJ_type
logger.info(
f"vdw_type not selected, will use first available for selected metals: {vdw_type:}")
f"vdw_type not selected, will use first available for selected metals: {LJ_type:}")
else:
for metal_name in self.metal_names:
if metal_name not in vdw_data[vdw_type] and f"{metal_name:}{self.metal_charge_dict[metal_name]:}" not in \
vdw_data[vdw_type]:
if metal_name not in vdw_data[LJ_type] and f"{metal_name:}{self.metal_charge_dict[metal_name]:}" not in \
vdw_data[LJ_type]:

metal_available_in = []
for vdw_type in vdw_data:
if (metal_name in vdw_data[vdw_type] or f"{metal_name:}{self.metal_charge_dict[metal_name]:}" in vdw_data[vdw_type]):
metal_available_in.append(vdw_type)
for LJ_type in vdw_data:
if (metal_name in vdw_data[LJ_type] or f"{metal_name:}{self.metal_charge_dict[metal_name]:}" in vdw_data[LJ_type]):
metal_available_in.append(LJ_type)

raise ValueError(f"Metal ({metal_name:}) unavailable in selected LJ library, but it seems it is present in {metal_available_in:}")
self.vdw_type = vdw_type
self.vdw_type = LJ_type

self.fingerprint_guess_list = fingerprint_guess_list
self.truncation_scheme = truncation_scheme
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@
# cage.parametrize(out_coord='new.pdb', out_topol='new.top')

os.chdir("/u/fd/chem1540/Downloads/rafa")
cage = supramolecular_structure('L2_m2l4.xyz', metal_charge_mult={'Pd': (2, 1)}, vdw_type='merz-opc')
cage = supramolecular_structure('L2_m2l4.xyz', metal_charge_mult={'Pd': (2, 1)}, LJ_type='merz-opc')
cage.prepare_initial_topology()
cage.parametrize(out_coord='new.pdb', out_topol='new.top')

Original file line number Diff line number Diff line change
Expand Up @@ -616,11 +616,11 @@
cage = supramolecular_structure('init_topol/noncovalent_complex.pdb',
topol='init_topol/noncovalent_complex.top',
metal_charges=metal_charges,
vdw_type=library_name, search_library=False)
LJ_type=library_name, search_library=False)
else:
cage = supramolecular_structure(f'crystal.pdb',
metal_charges=metal_charges,
vdw_type=library_name, search_library=False)
LJ_type=library_name, search_library=False)
cage.prepare_initial_topology(homoleptic_ligand_topol='linker0.top')

# cage.parametrize(out_topol='out_enormous.top', out_coord='out_enormous.pdb')
Expand Down
2 changes: 1 addition & 1 deletion metallicious/tests/example6_extract_pbc/example6.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import os

cage = supramolecular_structure('noncovalent_complex.pdb', {'Co': (2, 1)}, topol='noncovalent_complex.pdb', vdw_type='merz-opc')
cage = supramolecular_structure('noncovalent_complex.pdb', {'Co': (2, 1)}, topol='noncovalent_complex.pdb', LJ_type='merz-opc')

cage.extract_unique_metal_sites()

Expand Down

0 comments on commit b369821

Please sign in to comment.