### Install PyRosetta via pyrosetta-help
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/00_installation.md
Installation method using environment variables for credentials.
```bash
pip install pyrosetta-help
PYROSETTA_USERNAME=👾👾👾 PYROSETTA_PASSWORD=👾👾👾 install_pyrosetta
```
--------------------------------
### Start the Fragmenstein Web UI
Source: https://github.com/matteoferla/fragmenstein/blob/master/web/README.md
Execute the startup script from the web directory to initialize the backend and frontend services.
```bash
cd web
./start.sh
```
--------------------------------
### Install PyRosetta via Installer
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/00_installation.md
Modern method for installing PyRosetta without requiring manual password handling.
```bash
pip install pyrosetta-installer
python -c 'import pyrosetta_installer; pyrosetta_installer.install_pyrosetta()'
```
--------------------------------
### Install PLIP
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/00_installation.md
Installation commands for PLIP and its OpenBabel dependency using conda.
```bash
conda install -c conda-forge openbabel lxml
conda install -c conda-forge --no-deps plip
```
--------------------------------
### Install Fragmenstein Dependencies
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Installs necessary libraries and configures the environment for Fragmenstein. Includes error reporting setup and specific workarounds for Colab environment constraints.
```python
#@title Installation
import sys
#@markdown Press the play button on the top right hand side of this cell
#@markdown once you have checked the settings.
#@markdown You will be notified that this notebook is not from Google, that is normal.
#@markdown Send error messages to errors.matteoferla.com for logging?
#@markdown See [notebook-error-reporter repo for more](https://github.com/matteoferla/notebook-error-reporter)
report_errors = False #@param {type:"boolean"}
if report_errors:
!pip install notebook-error-reporter
from notebook_error_reporter import ErrorServer # noqa it is an option install
es = ErrorServer(url='https://errors.matteoferla.com', notebook='fragmenstein')
es.enable()
!pip install -U -q typing_extensions>=4.9
!pip install -U -q typeguard>=4.1.5
# weird glitch of the week:
try:
from typing_extensions import Buffer # needed by some external dependency somewhere
except ImportError:
import typing_extensions
typing_extensions.Buffer = None
!pip install -q rdkit rdkit-to-params biopython pyrosetta-help jsme_notebook
!pip install -q --upgrade plotly
# Installation for PLIP
# this wrongly assumes Mamba and Colab will stay at 3.10 for ever...
!wget -qnc https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-Linux-x86_64.sh
# Mamba at 3.10
#!wget -qnc https://github.com/conda-forge/miniforge/releases/download/23.3.1-1/Mambaforge-23.3.1-1-Linux-x86_64.sh
!bash Mambaforge-Linux-x86_64.sh -bfp /usr/local
python_version = f'{sys.version_info.major}.{sys.version_info.minor}'
sys.path.append(f'/usr/local/lib/python{python_version}/site-packages')
!mamba config --set auto_update_conda false
# PLIP gets confused. Weird install
!mamba install -y -c conda-forge openbabel lxml
!mamba install -y -c conda-forge --no-deps plip
import os
from importlib import reload
import pyrosetta_help as ph
from typing import *
# Colab no longer runs on 3.7
# keeping this just in case it's needed again
# hack to enable the backport:
import sys
if sys.version_info.major != 3 or sys.version_info.minor < 8:
!pip install -q singledispatchmethod
import functools
from singledispatchmethod import singledispatchmethod # noqa it's okay, PyCharm, I am not a technoluddite
functools.singledispatchmethod = singledispatchmethod
!pip install -q typing_extensions
import typing_extensions
import typing
for key, fun in typing_extensions.__dict__.items():
if key not in typing.__dict__:
setattr(typing, key, fun)
```
--------------------------------
### Install Fragmenstein
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/00_installation.md
Standard installation command for the Fragmenstein package.
```bash
python -m pip install fragmenstein
```
--------------------------------
### Setup SQLite Database Connection
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/pipeline.md
Initializes the SQLite database for storing results. Ensures data is automatically committed.
```python
import os, re
from sqlitedict import SqliteDict
import json
results = SqliteDict(db_name, encode=json.dumps, decode=json.loads, autocommit=True)
```
--------------------------------
### Install PyRosetta with Google Drive Option
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein.ipynb
Installs PyRosetta, with an option to download a release to Google Drive for faster subsequent installations. Requires PyRosetta academic license credentials.
```python
download_to_drive = False #@param {type:"boolean"}
download_path = '.' #@param {type:"string"}
username = 'boltzmann' #@param {type:"string"}
username.strip().lower()
password = 'constant' #@param {type:"string"}
hash_comparison_required = True #@param {type:"boolean"}
if download_to_drive and not use_drive:
raise ValueError('You said False to `use_drive` and True to `download_to_drive`? Very funny.')
elif download_to_drive:
ph.download_pyrosetta(username=username,
password=password,
path=download_path,
hash_comparison_required=hash_comparison_required)
else:
pass
ph.install_pyrosetta(username=username,
password=password,
path=download_path,
hash_comparison_required=hash_comparison_required)
reload(ph)
```
--------------------------------
### Install PyRosetta via Terminal
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/00_installation.md
Legacy method for downloading and installing PyRosetta using curl and tar.
```bash
curl -u 👾👾👾:👾👾👾https://graylab.jhu.edu/download/PyRosetta4/archive/release/PyRosetta4.Release.python38.linux/PyRosetta4.Release.python38.linux.release-NNN.tar.bz2 -o a.tar.bz2
tar -xf a.tar.bz2
cd PyRosetta4.Release.python38.linux
sudo pip3 install .
```
--------------------------------
### Setup Molecule and Reference Dropdowns
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Configures dropdown widgets for selecting a molecule to manipulate and a reference molecule. The 'options' should be populated with molecule names.
```python
mol_dropdown = widgets.Dropdown(
options=names,
tooltip='The molecule to move',
description='Molecule to rototranslate:',
disabled=False,
)
ref_dropdown = widgets.Dropdown(
options=names,
description='Ref molecule:',
disabled=False,
)
```
--------------------------------
### Install Fragmenstein and Dependencies
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein.ipynb
Installs the Fragmenstein package and its dependencies using pip. Includes a commented-out alternative for installing from a development branch.
```bash
!pip install smallworld_api fragmenstein
# Hey, future me, debugging are we? try:
# os.system('pip install git+https://github.com/matteoferla/Fragmenstein.git@dev-teo3')
```
--------------------------------
### Initialize Igor from PDB File
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/igor.md
Alternative initialization for Igor using a PDB file path. This method is useful when starting from existing PDB structures.
```python
Igor.from_pdbfile(pdb_file, constraint_filename)
```
--------------------------------
### Example Slurm Script for Fragmenstein Pipeline
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/04_cmd.md
This script is designed to be submitted to a Slurm cluster for running Fragmenstein pipelines. It includes environment variable setup, conda activation, and the main pipeline execution command. Ensure that the necessary environment variables like EXPERIMENT, TEMPLATE, HITS, and COMBO are set before submission.
```bash
#!/bin/bash
# Some note for myself on usage
# submit via:
# export EXPERIMENT='_foo'; export TEMPLATE='protein.pdb'; export HITS='hits.sdf';
# export COMBO=2; export SLACK_WEBHOOK='';
# sbatch /mtn/someshared-drive/frag.slurm.sh;
#SBATCH --job-name=fragmenstein
#SBATCH --chdir=/mtn/someshared-drive/mferla
#SBATCH --output=/mtn/someshared-drive/logs/slurm-error_%x_%j.log
#SBATCH --error=/mtn/someshared-drive/logs/slurm-error_%x_%j.log
#SBATCH --clusters=clustername-this-is-cluster-specific
#SBATCH --partition=this-is-kind-of-the-group-and-is-cluster-specific
#SBATCH --nodes=1
#SBATCH --exclusive
#SBATCH --export=NONE,SLACK_WEBHOOK,COMBO,EXPERIMENT,TEMPLATE,HITS
# -------------------------------------------------------
# Some slurm fluff for logs
export SUBMITTER_HOST=$HOST
export HOST=$( hostname )
export USER=${USER:-$(users)}
export DATA=/mtn/someshared-drive
export HOME=$DATA/$USER; # homeless
source /etc/os-release;
echo "Running $SLURM_JOB_NAME ($SLURM_JOB_ID) as $USER in $HOST which runs $PRETTY_NAME submitted from $SUBMITTER_HOST"
echo "Request had cpus=$SLURM_JOB_CPUS_PER_NODE mem=$SLURM_MEM_PER_NODE tasks=$SLURM_NTASKS jobID=$SLURM_JOB_ID partition=$SLURM_JOB_PARTITION jobName=$SLURM_JOB_NAME"
echo "Started at $SLURM_JOB_START_TIME"
echo "job_pid=$SLURM_TASK_PID job_gid=$SLURM_JOB_GID topology_addr=$SLURM_TOPOLOGY_ADDR home=$HOME cwd=$PWD"
# -------------------------------------------------------
# Some conda fluff
# assuming you have an appropriate conda installed in `$HOME/conda-slurm`
source $HOME/conda-slurm/etc/profile.d/conda.sh
conda activate base; # or whatever
pwd;
export EXPERIMENT=${EXPERIMENT:-'fragduo'}
export COMBO=${COMBO:-2}
export TEMPLATE=${TEMPLATE:-'template.pdb'}
export HITS=${HITS:-'hits.sdf'}
export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$CONDA_PREFIX;
#export N_CORES=$(cat /proc/cpuinfo | grep processor | wc -l);
export N_CORES=$SLURM_CPUS_ON_NODE;
nice -19 fragmenstein pipeline \
--template $TEMPLATE \
--input $HITS \
--n_cores $(($N_CORES - 1)) \
--suffix _$EXPERIMENT \
--max_tasks 5000 \
--sw_databases REAL-Database-22Q1.smi.anon \
--combination_size $COMBO \
--workfolder /tmp/$EXPERIMENT \
--timeout 600;
rm -rf /tmp/$EXPERIMENT;
curl -X POST -H 'Content-type: application/json' --data '{"text":"'$EXPERIMENT' x2 complete"}' $SLACK_WEBHOOK
# -------------------------------------------------------
echo 'complete'
exit 0
```
--------------------------------
### Install and Enable Colab Widgets
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Installs the py3Dmol package and enables custom widget manager for Google Colaboratory.
```python
!pip install py3Dmol -q
from google.colab import output # noqa (It's a colaboratory specific repo)
output.enable_custom_widget_manager()
```
--------------------------------
### Install Fragmenstein and Dependencies
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Installs the smallworld_api and fragmenstein packages. This is a prerequisite for using Fragmenstein functionalities.
```python
!pip install smallworld_api fragmenstein -q
```
--------------------------------
### Example ringcore expansion data structure
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/monster/no_template.md
The dictionary structure returned by _get_expansion_data for a ringcore atom.
```json
{
'_ori_name': 'toluene',
'_ori_i': -1,
'_ori_is': '[0, 5, 4, 3, 2, 1]',
'_neighbors': '[[1, 5], [4, 6, 0], [3, 5], [2, 4], [1, 3], [0, 2]]',
'_xs': '[1.5, 0.75, -0.75, -1.5, -0.75, 0.75]',
'_ys': '[0.0, 1.299, 1.299, 0.0, -1.299, -1.299]',
'_zs': '[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]',
'_elements': '["C", "C", "C", "C", "C", "C"]',
'_bonds': '[["AROMATIC", "AROMATIC"], ["AROMATIC", "SINGLE", "AROMATIC"], ["AROMATIC", "AROMATIC"], ["AROMATIC", "AROMATIC"], ["AROMATIC", "AROMATIC"], ["AROMATIC", "AROMATIC"]]'}
```
--------------------------------
### Setup Rotation and Distance Widgets
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Sets up integer text widgets for specifying rotation angles in degrees and distances in Angstroms. Default values are set to 0.
```python
theta_text = widgets.IntText(
value=0,
description='Angle [°]',
disabled=False
)
distance_text = widgets.IntText(
value=0,
description='Distance [Ã…]',
disabled=False
)
```
--------------------------------
### Custom Mapping Format Example 1
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/monster/custom_mapping.md
Illustrates the basic format for custom mapping, where keys are hit names and values are dictionaries mapping hit atom index to followup atom index.
```python
mapping = { 'hit1': {1:1,2:5} 'hit2': {3:3,4:4,4:6}}
```
--------------------------------
### Create Molecule Widgets
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Sets up interactive widgets for molecule creation, including text input for molecule names and buttons to add or discard molecules. This requires `ipywidgets` and `jsme-notebook` to be installed.
```python
from jsme_notebook import JSMENotebook
from IPython.display import display
import ipywidgets as widgets
from rdkit import Chem
from rdkit.Chem import AllChem
from fragmenstein import display_mols
import re, os
# -------------------------------------------------
name_input = widgets.Text(description='Name molecule', value='')
add_button = widgets.Button(description="Add molecule", icon='plus')
clear_button = widgets.Button(description="Discard molecules", icon='trash')
```
--------------------------------
### Setup Atom Index and Translation Widgets
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Initializes integer text widgets for specifying atom indices and translation distances along the X, Y, and Z axes. Default values are set to 0.
```python
atom_idx0_text = widgets.IntText(
value=0,
description='1st atom:',
disabled=False
)
atom_idx1_text = widgets.IntText(
value=1,
description='2nd atom:',
disabled=False
)
atom_idx2_text = widgets.IntText(
value=1,
description='3rd atom:',
disabled=False
)
x_text = widgets.IntText(
value=0,
description='x [Ã…]',
disabled=False
)
y_text = widgets.IntText(
value=0,
description='y [Ã…]',
disabled=False
)
z_text = widgets.IntText(
value=0,
description='z [Ã…]',
disabled=False
)
```
--------------------------------
### Instantiate and Use Wictor
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/notes/no_minimisation.md
Instantiate the custom `Wictor` class with provided molecular data and perform combination. This example assumes `Mac1` is available for demo data.
```python
Wictor = ... # see above
from fragmenstein.demo import Mac1
Wictor.capture_rdkit_log()
#Wictor.enable_stdout()
Wictor.error_to_catch = ()
wicky = Wictor(hits=Mac1.get_n_filtered_mols(2),
pdb_block=Mac1.get_template(),
)
wicky.combine()
wicky.to_nglview()
```
--------------------------------
### Custom Mapping Format Example 2 (Special Index -1)
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/monster/custom_mapping.md
Demonstrates the use of the special followup index -1, which signifies that the hit index is not provided. This is for clarity and not intended for direct use.
```python
mapping = { 'hit1': {1:1,2:5, 3:-1} 'hit2': {3:3,4:4,4:6}}
```
--------------------------------
### Initialize Project Settings
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/pipeline.md
Sets up project-specific variables like input folder, number of cores, output path, and database name.
```python
project = 'mergers'
input_foldername = 'input'
##############################################
cores = 20
out_path = f'{project}'
db_name = f'{project}.sqlite'
##############################################
```
--------------------------------
### Define Function to Get Best Hit PDB Filename
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/victor.md
A function that determines the closest hit PDB file from a list of hit codes, targeting a specific residue and atom. This is used to select a starting point for reanimation.
```python
def get_best(hit_codes):
return Victor.closest_hit(pdb_filenames=[f'{mpro_folder}/Mpro-{i}_0/Mpro-{i}_0_bound.pdb' for i in hit_codes],
target_resi=145,
target_chain='A',
target_atomname='SG',
ligand_resn='LIG')
```
--------------------------------
### Set up Fragmenstein Working Directories
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Creates necessary directories for Fragmenstein data, input, and output. Changes the current working directory to 'fragmenstein_data'.
```python
# make folders in _path
working_folder = 'fragmenstein_data'
input_folder = 'input'
output_folder = 'output'
if not os.path.exists(working_folder):
os.mkdir(working_folder)
os.chdir('fragmenstein_data')
for folder in (input_folder, output_folder):
if not os.path.exists(folder):
os.mkdir(folder)
```
--------------------------------
### Initialize and Minimize with Igor
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/igor.md
Initialize Igor with a Pose and constraint filename, then run minimization for a specified number of steps. Ensure pose is a pyrossetta.Pose instance.
```python
e = Igor(pose, constraint_filename)
e.minimize(10)
```
--------------------------------
### Initialize and place a molecule
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/changelog_0.6.md
Demonstrates the standard workflow for initializing a Monster object and placing a molecule.
```python
monster = Monster(hits)
monster.place(mol)
monster.positioned_mol
```
--------------------------------
### Configure File Paths and Environment
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/pipeline.md
Sets up directory paths and ensures the target folder exists for output files.
```python
title = 'Fragmenstein NSP3 Mergers'
#gitfolder=f'/well/brc/matteo/{repo_name}'
gitfolder=f'/well/brc/matteo/NSP3/git-repo'
sdfile=f'{gitfolder}/{folder}/mergers.sdf'
xlsfile=f'{gitfolder}/{folder}/mergers.xlsx'
targetfolder=f'{gitfolder}/{folder}'
import os, re
if not os.path.exists(targetfolder):
os.mkdir(targetfolder)
target = 'Mike'
#target = 'Excel'
#target = 'Frag'
```
--------------------------------
### Initialize and Execute Fragmenstein Merger
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/monster/monster_full.md
Demonstrates loading hit molecules, initializing the Fragmenstein merger with a followup compound, and generating output structures.
```python
hits = [Chem.MolFromMolFile(f'../Mpro/Mpro-{i}_0/Mpro-{i}_0.mol') for i in ('x0692', 'x0305', 'x1249')]
followup = Chem.MolFromSmiles('CCNc1nc(CCS)c(C#N)cc1CN1C(CCS)CN(C(C)=O)CC1')
monster = Fragmenstein(followup, hits)
#monster = Fragmenstein(followup, hits, draw=True) for verbosity in a Jupyter notebook
monster.make_pse('test.pse')
display(monster.scaffold)
display(monster.chimera) # merger of hits but with atoms made to match the to-be-aligned mol
display(monster.positioned_mol) # followup aligned
# further alignments... not correct way of tho
monster.initial_mol = new_mol
aligned = monster.place_from_map(new_mol)
```
--------------------------------
### Initialize Visualization Environment
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Imports necessary IPython and ipywidgets modules and defines a helper function for HTML headers.
```python
from IPython.display import clear_output, HTML, display
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
headerify: Callable[[str], HTML] = lambda header: HTML(f'
{header}
')
clear_output()
```
--------------------------------
### Install Fragmenstein Dependencies
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein.ipynb
Installs necessary Python packages for Fragmenstein, including py3Dmol, rdkit, and pyrosetta-help. It also includes a check for Colab environment and optional installation of notebook-error-reporter and typing_extensions for older Python versions.
```python
#@title Installation
#@markdown Press the play button on the top right hand side of this cell
#@markdown once you have checked the settings.
#@markdown You will be notified that this notebook is not from Google, that is normal.
#@markdown Send error messages to errors.matteoferla.com for logging?
#@markdown See [notebook-error-reporter repo for more](https://github.com/matteoferla/notebook-error-reporter)
report_errors = False #@param {type:"boolean"}
if report_errors:
!pip install notebook-error-reporter
from notebook_error_reporter import ErrorServer
es = ErrorServer(url='https://errors.matteoferla.com', notebook='fragmenstein')
es.enable()
!pip install -q py3Dmol rdkit rdkit-to-params biopython pyrosetta-help jsme_notebook
!pip install -q --upgrade plotly
import os
import py3Dmol
from importlib import reload
import pyrosetta_help as ph
from typing import *
# Muppet-proofing: are we in colab?
assert ph.get_shell_mode() == 'colab', 'This is a colab notebook, if running in Jupyter notebook, the installation is different'
# Colab still runs on 3.7
# hack to enable the backport:
import sys
if sys.version_info.major != 3 or sys.version_info.minor < 8:
!pip install -q singledispatchmethod
import functools
from singledispatchmethod import singledispatchmethod # noqa it's okay, PyCharm, I am not a technoluddite
functools.singledispatchmethod = singledispatchmethod
!pip install -q typing_extensions
import typing_extensions
import typing
for key, fun in typing_extensions.__dict__.items():
if key not in typing.__dict__:
setattr(typing, key, fun)
```
--------------------------------
### Fragmenstein Pipeline Help
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/04_cmd.md
Display the command-line usage and available options for the pipeline tool.
```text
usage: fragmenstein pipeline [-h] -t TEMPLATE -i INPUT [-o OUTPUT] [-r RANKING] [-c CUTOFF] [-q QUICK] [-d SW_DIST] [-l SW_LENGTH] [-b SW_DATABASES [SW_DATABASES ...]] [-s SUFFIX]
[--workfolder WORKFOLDER] [--victor VICTOR] [-n N_CORES] [-m COMBINATION_SIZE] [-k TOP_MERGERS] [-e TIMEOUT] [-x MAX_TASKS] [-z BLACKLIST] [-j WEIGHTS] [-v]
options:
-h, --help show this help message and exit
-t TEMPLATE, --template TEMPLATE
Template PDB file
-i INPUT, --input INPUT
Hits SDF file
-o OUTPUT, --output OUTPUT
Output folder
-r RANKING, --ranking RANKING
Ranking method
-c CUTOFF, --cutoff CUTOFF
Joining cutoff
-q QUICK, --quick QUICK
Quick reanimation
-d SW_DIST, --sw_dist SW_DIST
SmallWorld distance
-l SW_LENGTH, --sw_length SW_LENGTH
SmallWorld length
-b SW_DATABASES [SW_DATABASES ...], --sw_databases SW_DATABASES [SW_DATABASES ...]
SmallWorld databases. Accepts multiple
-s SUFFIX, --suffix SUFFIX
Suffix for output files
--workfolder WORKFOLDER
Location to put the temp files
--victor VICTOR Which victor to use: Victor, OpenVictor or Wictor
-n N_CORES, --n_cores N_CORES
Number of cores
-m COMBINATION_SIZE, --combination_size COMBINATION_SIZE
Number of hits to combine in one step
-k TOP_MERGERS, --top_mergers TOP_MERGERS
Max number of mergers to followup up on
-e TIMEOUT, --timeout TIMEOUT
Timeout for each merger
-x MAX_TASKS, --max_tasks MAX_TASKS
Max number of combinations to try in a batch
-z BLACKLIST, --blacklist BLACKLIST
Blacklist file
-j WEIGHTS, --weights WEIGHTS
JSON weights file
-v, --verbose verbose
```
--------------------------------
### Configure Fragmenstein Logging and Settings
Source: https://context7.com/matteoferla/fragmenstein/llms.txt
Demonstrates how to configure logging levels (stdout and file) and working directory for Fragmenstein. Also shows how to adjust Monster settings and access the logger directly.
```python
from fragmenstein import Victor, Igor
import logging
# Enable stdout logging
Victor.enable_stdout(logging.INFO)
# Or log to file
Victor.enable_logfile('fragmenstein.log', logging.DEBUG)
# Set working directory for output files
Victor.work_path = 'output/'
# Access the logger directly
Victor.journal.info("Starting Fragmenstein run")
# Configure Monster settings via Victor
Victor.monster_throw_on_discard = False # Don't raise error when hits are discarded
Victor.monster_mmff_minisation = True # Enable MMFF minimization in Monster
Victor.quick_reanimation = False # Full minimization attempts
# Configure via environment variables
# export FRAGMENSTEIN_MONSTER_THROW_ON_DISCARD=false
# export FRAGMENSTEIN_WORK_PATH=/tmp/fragmenstein
```
--------------------------------
### Install Fragmenstein Dependencies
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Installs required Python packages for Fragmenstein, py3Dmol, and related tools. Ensure this runs before importing modules that depend on these packages.
```bash
!pip install -q py3Dmol fragmenstein smallworld-api notebook-error-reporter jsme_notebook
```
--------------------------------
### Refresh Python Site Packages
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Ensures that the Python environment is up-to-date with installed packages.
```python
# refresh imports
import site
site.main()
```
--------------------------------
### Initialize PyRosetta Environment
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein.ipynb
Configures PyRosetta with specific options for ligand handling and logging.
```python
#@title Start PyRosetta
#@markdown Leave alone and just run it.
#@markdown Only one that you might want to change is `ignore_waters`
#@markdown as merging a ligand with its watershell may be a reasonable thing to do
#@markdown in extreme circumstances —like not even Chuck Norris could find a followup.
import pyrosetta, logging
import pyrosetta_help as ph
#@markdown Do not optimise hydrogen on loading:
no_optH = False #@param {type:"boolean"}
#@markdown Ignore (True) or raise error (False) if novel residue (e.g. ligand) — **don't tick this**.
ignore_unrecognized_res = False #@param {type:"boolean"}
#@markdown Use autogenerated PDB residues are often weird (bad geometry, wrong match, protonated etc.): —best do it properly and parameterise it, so **don't tick this**.
load_PDB_components = False #@param {type:"boolean"}
#@markdown Ignore all waters:
ignore_waters = True #@param {type:"boolean"}
extra_options = ph.make_option_string(no_optH=no_optH,
ex1=None,
ex2=None,
mute='all',
ignore_unrecognized_res=ignore_unrecognized_res,
load_PDB_components=load_PDB_components,
ignore_waters=ignore_waters)
# capture to log
# circuitous as I needed to debug...
logger = ph.configure_logger()
logger.handlers[0].setLevel(logging.WARNING) # logging.WARNING = 30
pyrosetta.init(extra_options=extra_options,
#set_logging_handler=True
)
```
--------------------------------
### Initialize Molecule Management Widgets
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Sets up the UI components for molecule input and display, including a JSME editor and a grid layout for controls.
```python
output = widgets.Output(layout={'border': '1px solid black'})
uploader = widgets.FileUpload(icon='upload')
jsme = JSMENotebook() # outputs to display as is not a widget
grid = widgets.GridspecLayout(1, 4)
grid[0,0] = name_input
grid[0,1] = add_button
grid[0,2] = uploader
grid[0,3] = clear_button
display(grid, output)
```
--------------------------------
### Initialize Laboratory with PLIP
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/02_usage.md
Enable PLIP interaction prediction within the Laboratory wrapper.
```python
lab = Laboratory(pdbblock=pdbblock, run_plip=True)
```
--------------------------------
### Minimize with Coordinate Constraints
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/igor.md
Run minimization with coordinate constraints. If no constraints are in the file, `default_coord_constraint=True` will enforce constraints to the starting coordinates.
```python
e.minimise(default_coord_constraint=True)
```
--------------------------------
### Initialize Pyrosetta and Prepare Protein Template
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/pipeline.md
Initializes Pyrosetta, downloads a CCP4 map, and prepares a protein template from a PDB file with non-standard residue parameters. It then relaxes the pose using energy-based restraints and saves the result. Finally, it uses PyMOL to clean the template by removing a specific residue and saving it.
```python
pdbcode = '6WOJ' # ADP bound.
from fragmenstein import Victor, Igor
Igor.download_map(pdbcode, pdbcode+'.ccp4')
# topology
from rdkit_to_params import Params
p = Params.from_smiles_w_pdbfile(pdb_file='mono.pdb',
smiles='Nc1ncnc2n(cnc12)[C@@H]3O[C@H](CO[P@@]([O-])(=O)O[P@@]([O-])(=O)OC[C@H]4O[C@@H](O)[C@H](O)[C@@H]4O)[C@@H](O)[C@H]3O',
name='APR',
proximityBonding=False)
p.dump('APR.params')
# start
import pyrosetta
pyrosetta.init(extra_options='-no_optH false -mute all -ex1 -ex2 -ignore_unrecognized_res false -load_PDB_components false -ignore_waters false')
#import nglview
#nglview.show_rosetta(p.test())
params_file = 'APR.params'
pdbfile = 'mono.pdb' # 6WOJ manually inspected.
pose = pyrosetta.Pose()
params_paths = pyrosetta.rosetta.utility.vector1_string()
params_paths.extend([params_file])
pyrosetta.generate_nonstandard_residue_set(pose, params_paths)
pyrosetta.rosetta.core.import_pose.pose_from_file(pose, pdbfile)
Igor.relax_with_ED(pose=pose, ccp4_file=pdbcode+'.ccp4')
pose.dump_pdb('mono.r.pdb')
# this part makes no sense, but is just an example —in reality checking the result visually would make more sense.
# or it could be done in Pyrosetta.
import pymol2
with pymol2.PyMOL() as pymol:
pymol.cmd.load('mono.r.pdb')
pymol.cmd.remove('resn APR')
pymol.cmd.save('template.pdb')
```
--------------------------------
### Use Monster without Pyrosetta
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/03_examples.md
Import and use the Monster class from Fragmenstein without requiring Pyrosetta to be installed. Useful for licensing reasons.
```python
from fragmenstein import Monster
```
--------------------------------
### Setup Axis Selection Dropdowns
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Configures dropdown widgets for selecting rotation or translation axes (X, Y, Z). Default selections are 'x' and 'y'.
```python
axis0_dropdown = widgets.Dropdown(
options=['x', 'y', 'z'],
value='x',
description='1st axis:',
disabled=False,
)
axis1_dropdown = widgets.Dropdown(
options=['x', 'y', 'z'],
value='y',
description='2nd axis:',
disabled=False,
)
```
--------------------------------
### Initialize Pyrosetta with Helper Function
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/03_examples.md
Initialize Pyrosetta using a helper function from the pyrosetta_help module for cleaner option string generation.
```python
import pyrosetta
from pyrosetta_help import make_option_string
extras = make_option_string(no_optH=False,
mute='all',
ignore_unrecognized_res=False,
load_PDB_components=False)
pyrosetta.init(extra_options=extras)
```
--------------------------------
### Get SMILES from Dictionary
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein.ipynb
Retrieves the SMILES string for a given molecule name from a pre-parsed SMILES dictionary. Issues a warning if the name is not found.
```python
def get_smiles(filename: str, smilesdex: Dict[str, str]) -> Union[None, str]:
name = os.path.splitext(filename)[0]
if name in smilesdex:
return smilesdex[name]
else:
warn(f'Could not find matching SMILES to {name}')
return None
```
--------------------------------
### Initialize Pyrosetta and Import Fragmenstein Classes
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/victor.md
Initializes the pyrosetta library with specific options and imports necessary classes from the fragmenstein package. Ensure pyrosetta is initialized before other imports.
```python
import pyrosetta
pyrosetta.init(extra_options='-no_optH false -mute all -ignore_unrecognized_res true -load_PDB_components false')
from fragmenstein import Igor, Monster, Victor
import logging, csv, json
from rdkit import Chem
from rdkit.Chem import AllChem
```
--------------------------------
### Import Fragmenstein without PyRosetta
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/notes/no_minimisation.md
Import `Victor` from Fragmenstein. A `RuntimeWarning` will indicate that PyRosetta is not installed and a mock object is loaded. Calls to PyRosetta-dependent methods will fail.
```python
from fragmenstein import Victor # RuntimeWarning: PyRosetta is not installed. A mock object is loaded. Any calls will fail.
from fragmenstein import __version__ as fragn_version
print(fragn_version) # 0.9.12.6
```
--------------------------------
### Initialize Pyrosetta with Options
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/03_examples.md
Initialize Pyrosetta with specific options to control behavior like H-bond optimization and unrecognized residue handling.
```python
import pyrosetta
pyrosetta.init(extra_options='-no_optH false -mute all -ignore_unrecognized_res false -load_PDB_components false')
```
--------------------------------
### Enable Debug Logging for Victor
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/notes/troubleshooting_example.md
Enable stdout logging for the Victor class at the DEBUG level to get more detailed information during execution. This is useful for diagnosing cryptic errors.
```python
import logging
Victor.enable_stdout(level=logging.DEBUG)
```
--------------------------------
### Initialize Fragmenstein Laboratory
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein.ipynb
Sets up the Fragmenstein Laboratory with specified parameters like working path, cutoffs, and error handling. It then combines hits using the provided PDB block and covalent residue information.
```python
import os, re
import pyrosetta, logging
import pandas as pd
from rdkit import Chem
from fragmenstein import Victor, Laboratory
Victor.work_path = output_folder
Victor.monster_throw_on_discard = True # stop this merger if a fragment cannot be used.
Victor.monster_joining_cutoff = joining_cutoff # Ã…
Victor.quick_reanimation = quick_reananimation # for the impatient
Victor.error_to_catch = Exception # stop the whole laboratory otherwise
#Victor.enable_stdout(logging.ERROR)
Victor.enable_logfile(os.path.join(output_folder, 'demo.log'), logging.ERROR)
# calculate !
lab = Laboratory(pdbblock=pdbblock, covalent_resi=covalent_resi)
n_cores = 1 #@param {type:"integer"}
combinations:pd.DataFrame = lab.combine(hits, n_cores=n_cores)
```
--------------------------------
### Import Necessary Libraries for Molecule Manipulation
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Imports essential libraries for molecule manipulation, including Fragmenstein, ipywidgets, RDKit, and SmallWorld API. Ensure these libraries are installed before use.
```python
from warnings import warn
from fragmenstein import Walton, Monster
from ipywidgets import TwoByTwoLayout
from IPython.display import clear_output, display, HTML
from functools import partial
from rdkit import Chem, Geometry
from rdkit.Chem import PandasTools
import pandas as pd
from smallworld_api import SmallWorld
from warnings import warn
from threading import Lock
from jsme_notebook.rdkit import JSMERDKit
```
--------------------------------
### Initialize PyRosetta with Generalised Potentials
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/generalised_potentials.md
Configure PyRosetta options to enable the beta_genpot scorefunction. This must be done during the initial call to pyrosetta.init.
```python
import pyrosetta_help as ph
import pyrosetta
extra_options= ph.make_option_string(no_optH=False,
ex1=True,
ex2=True,
gen_potential=True,
score=dict(weights='beta_genpot_cart'),
#mute='all',
ignore_unrecognized_res=False, # raise error if unrecognized
load_PDB_components=False,
ignore_waters=False)
# weights can be one of ['beta_genpot', 'beta_genpot_cart', 'beta_genpot_cst', 'beta_genpot_soft']
pyrosetta.init(extra_options=extra_options)
# no idea why I get this, but it is not an issue:
# core.init.score_function_corrections: [ WARNING ] Flag -beta_nov16 is set but either -weights are also specified or this is being used with the genpot score function. Not changing input weights file!
# core.init.score_function_corrections: [ WARNING ] Flag -gen_potential is set but -weights are also specified. Not changing input weights file!
scorefxn = pyrosetta.get_fa_scorefxn()
assert scorefxn.get_name() == 'beta_genpot_cart'
```
--------------------------------
### Configure Fragmenstein Wictor and Laboratory
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Sets up global parameters for Wictor and Laboratory, including working path, error handling, and logging. Ensure output_folder is defined before execution.
```python
import os, re, logging
import pandas as pd
from rdkit import Chem
from fragmenstein import Wictor, Laboratory
Wictor.work_path = output_folder
Wictor.monster_throw_on_discard = True # stop this merger if a fragment cannot be used.
Wictor.monster_joining_cutoff = joining_cutoff # Ã…
Wictor.error_to_catch = Exception # stop the whole laboratory otherwise
Wictor.enable_stdout(logging.ERROR)
Wictor.enable_logfile(os.path.join(output_folder, 'demo.log'), logging.ERROR)
Laboratory.Victor = Wictor
```
--------------------------------
### Custom Mapping Format Example 3 (Special Index -2)
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/monster/custom_mapping.md
Shows the use of the special followup index -2, which indicates that the hit atom index will not match any followup index.
```python
mapping = { 'hit1': {1:1,2:5, 3:-2} 'hit2': {3:3,4:4,4:6}}
```
--------------------------------
### Load Demo Data with Mac1
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/03_examples.md
Load template and hit list data using the Mac1 class from fragmenstein.demo. Useful for testing.
```python
from fragmenstein.demo import MPro, Mac1
pdbblock: str = Mac1.get_template()
hitname: str = ...
for hitname in Mac1.get_hit_list():
Mac1.get_hit(hitname)
...
```
--------------------------------
### Initialize Fragmenstein Environment
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_playground.ipynb
Sets up the Fragmenstein environment by importing necessary classes and configuring logging. This snippet also initializes the `Walton` object, which is a core component for running Fragmenstein.
```python
from fragmenstein import Walton, display_mols, Victor
import logging
Victor.enable_stdout(logging.ERROR)
walton = Walton([])
```
--------------------------------
### Initialize and Run Fragmenstein Laboratory
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Initializes the Laboratory with a PDB block and covalent residue information, then runs the combination process. Requires `pdbblock` and `covalent_resi` to be defined.
```python
# calculate !
lab = Laboratory(pdbblock=pdbblock, covalent_resi=covalent_resi)
n_cores = 1 #@param {type:"integer"}
combinations:pd.DataFrame = lab.combine(hits, n_cores=n_cores)
```
--------------------------------
### Load Molecules from GitHub Repository
Source: https://github.com/matteoferla/fragmenstein/blob/master/colab-notebooks/colab_fragmenstein_Wictor.ipynb
Fetches molecular files from a GitHub repository and parses them. Requires PyGithub installation. The `_content2mol` function handles individual file content, and `hits_from_github` orchestrates the retrieval from a specified folder.
```python
!pip install PyGithub
from github import Github
from github.ContentFile import ContentFile
import os
from typing import Tuple, List
from rdkit import Chem
# -------------------------------------------------------
def _content2mol(content:ContentFile) -> Chem.Mol:
if content.path.count('-') > 1:
return
# "molfiles/diamond-x0158_B.mol"
filename = os.path.split(content.path)[1]
if not some_filter(filename):
return None
mol: Chem.Mol = Chem.MolFromMolBlock( content.decoded_content.decode('utf8') )
mol.SetProp('_Name', filename)
return mol
def get_repo(username:str, repo_name:str) -> Github:
return Github().get_user(username).get_repo(repo_name)
def hits_from_github(username:str, repo_name:str, folder:str) -> List[Chem.Mol]:
repo = get_repo(username, repo_name)
return list(filter(lambda x: x is not None, map(_content2mol, repo.get_contents(folder))))
# ----------------- Change these:
all_hits:List[Chem.Mol] = hits_from_github(username='matteoferla',
repo_name='NSP3-macrodomain',
folder='molfiles')
hits = all_hits[:20]
pdbblock:str = get_repo(username='matteoferla', repo_name='NSP3-macrodomain').get_contents("molfiles/template.pdb").decoded_content.decode('utf8')
```
--------------------------------
### Fragmenstein CLI: Full Pipeline with SmallWorld Catalogue Search
Source: https://context7.com/matteoferla/fragmenstein/llms.txt
Command to run the full Fragmenstein pipeline, including SmallWorld catalogue search, with specified parameters for template, input hits, cores, combination size, database, length, timeout, and output.
```bash
fragmenstein pipeline \
--template template.pdb \
--input hits.sdf \
--n_cores 8 \
--combination_size 2 \
--sw_databases REAL-Database-22Q1.smi.anon \
--sw_length 50 \
--timeout 600 \
--output results/
```
--------------------------------
### Generate and Augment Chemical Results Table
Source: https://github.com/matteoferla/fragmenstein/blob/master/documentation/further-detail/pipeline.md
Example script to generate a chemical results table from an SQLite database, calculate atom counts for hits, and assign new columns for atom differences. Requires RDKit and Fragmenstein.
```python
##############################################
project = 'mergers'
from fragmenstein import Victor
Victor.work_path = project
db_name = f'{project}.sqlite'
result_table = get_table(db_name, mols=True)
#result_table
# shoot. I forgot to count atoms in hits...
atom_Ns = {}
for folder in ('newinputs',): #'input', 'UCSF2-hits', 'frags'):
for file in os.listdir(folder):
if '.mol' in file:
mol = Chem.MolFromMolFile(os.path.join(folder, file), sanitize=False)
if mol is None:
atom_Ns[file.replace('.mol','')] = 0 # float nan?
else:
mol = Chem.GetMolFrags(mol, asMols=True)[0] # just in case
atom_Ns[file.replace('.mol','')] = mol.GetNumAtoms()
# add atom n
hit_counter = lambda hits: sum([atom_Ns[hit] for hit in hits])
merge_counter = lambda row: row.N_hit_atoms - row.N_unconstrained_atoms - row.N_constrained_atoms
result_table = result_table.assign(N_hit_atoms=result_table.regarded.apply(hit_counter))
result_table = result_table.assign(N_diff_atoms=result_table.apply(merge_counter, axis='columns'))
result_table
```