Skip to content

Repository files navigation

GenCReM: molecule optimization, scaffold decoration, de novo generation guided by explainable docking

Table Of Contents

Features

  • Molecule optimization, scaffold decoration, de novo generation tasks
  • Based on a genetic algorithm (GA)
  • Uses the CReM[1] engine to generate feasible, synthetically accessible molecules
  • Makes it easy to specify physicochemical property limits for generated molecules
  • Optimizes docking score, number of protein-ligand interactions, and RMSD
  • Indirectly controls synthetic accessibility via CReM parameters
  • Explores chemical space via an explainable docking workflow that preserves well-fitted 3D fragments while editing suboptimal atoms

How a run works

One iteration of the genetic algorithm:

  1. Mutation. Every molecule of the population is sent to CReM, which replaces one fragment of it by fragments with the same context taken from the fragment database (-d/--db, --radius). Atoms which are protected are never touched, and the size of the exchanged fragment is controlled by --max_size, --max_inc and --min_inc.
  2. Filtering. A candidate is discarded when it exceeds the physicochemical limits (--mw, --rtb, --logp, --tpsa), when its similarity to the input molecule is outside --min_tanimoto / --max_tanimoto, or when it is already stored in the output DB. A molecule is mutated until it produces a molecule which is not in the DB yet, so no docking time is spent on molecules which are already known.
  3. Docking. The new molecules are docked with EasyDock (--program, --config), optionally after protonation (--protonation) and tautomer generation.
  4. Atom contributions. Unless --no_contrib is given, every atom is masked and the molecule is rescored, which shows which atoms contribute to the binding. Well-fitted parts are protected in the next iteration, poorly fitted ones are offered to the mutation.
  5. Fitness. The docking scores of the population are scaled with the default softmax normalization, and the terms which were asked for - the similarity to the reference protein-ligand contacts (--plif) and the RMSD to the parent pose (--rmsd) - are combined with them as a geometric mean.
  6. Selection. In --mode parallel every molecule competes with its own child; in --mode survival the whole population is drawn from the parents and their children by fitness, optionally keeping the best molecule (--elitism).
  7. Bookkeeping. A molecule which produced nothing new is marked as a dead end and replaced, and a molecule which has not been improved for --max_lifetime iterations is restarted to an input molecule.

The run ends when one of the stop criteria is met: --n_iteration generations, --n_mols molecules, convergence (--stop_if_converged), or an exhausted chemical space.

Return to the TOC

Installation

Dependencies

  • Python (>=3.11)
conda env create --file environment.yaml
conda activate gencrem

pip install crem==0.2.17
pip install git+https://github.com/ci-lab-cz/easydock.git

git clone https://github.com/ci-lab-cz/crem-dock-ga.git

Important

CReM version. Use crem==0.2.17.

  • crem>=0.3 builds mutated molecules with molzip instead of RDKit reactions, so the products no longer carry the react_atom_idx property. The protected atoms of a parent (protected_user_ids, see Preserve the substructure/scaffold of the input molecule) can then not be transferred to its children: the run works, but the molecules are stored without protected atoms and the scaffold is not preserved (a warning is written for every such molecule).

EasyDock 1.2.0 and newer versions with the easydock.dock layout are both supported. For protonation, install the required packages (MolGPKA, UNI-PKA, etc.) from the easydock installation page.

Usage

Note

Fragment databases are required for the CReM generator and can be found here.

python gencrem.py -h

usage: gencrem.py [-h] [-i FILENAME] -o FILENAME [--hostfile FILENAME] [--log FILENAME] [--prefix STRING] [-c NCPU] [--seed SEED] [-d fragments.db] [-r RADIUS]
                  [--min_freq MIN_FREQ] [--replace_cycles] [--max_size MAX_SIZE] [--max_inc MAX_INC] [--min_inc MIN_INC] [--n_iteration N_ITERATION]
                  [--n_mols N_MOLS] [--population_size POPULATION_SIZE] [--population_replicas {1}] [--mutation_rate {1}] [--elitism]
                  [--fitness_sharing FITNESS_SHARING] [--scaffold_quota SCAFFOLD_QUOTA]
                  [--no_diverse_fill] [--archive_refresh_fraction ARCHIVE_REFRESH_FRACTION]
                  [--max_lifetime MAX_LIFETIME]
                  [--mode {parallel,survival}] [--stop_if_converged]
                  [--convergence_rate CONVERGENCE_RATE] [--convergence_method {duplication,improvement}] [--no_duplicates] [--no_contrib] [--rmsd RMSD] [--mw MW]
                  [--allow_duplicates] [--rtb RTB] [--logp LOGP] [--tpsa TPSA] [--plif [PLIF ...]]
                  [--plif_map [scaled values for each PLIF similarity value: 0 contacts, 1 contact ... any Nth contacts ...]] [--no_tautomerization] [--no_redock]
                  [--protonation PROTONATION] [--protein_h protein.pdb] [--program STRING] [--config FILENAME]

Fragment mutation within the binding pocket using Docking contributions.

options:
  -h, --help            show this help message and exit
  -i FILENAME, --input_frags FILENAME
                        SMILES file with input fragments/molecules or SDF file with 3D coordinates of pre-aligned input fragments (e.g. from PDB complexes). If SDF contains
                        a <protected_user_ids> field (comma-separated 1-based indices) these atoms will be protected from mutation. This argument can be omitted if an
                        existing output DB is specified; docking will then continue from the last successful iteration. Optional. (default: None)
  -o FILENAME, --output FILENAME
                        SQLite DB with docking results. If an existing DB was supplied, input fragments (if any) will be ignored and the program will continue docking
                        from the last successful iteration. (default: None)
  --hostfile FILENAME   text file with addresses of nodes of a Dask SSH cluster. Most typically, it can be passed as the $PBS_NODEFILE variable from inside a PBS script.
                        The first line in this file will be the address of the scheduler running on the standard port 8786. If omitted, calculations run on a
                        single machine as usual. (default: None)
  --log FILENAME        log file to collect progress and debug messages. If omitted, the log file with the same name as output DB will be created. (default: None)
  --prefix STRING       prefix to add to all names; useful if multiple runs are analyzed together. (default: None)
  -c NCPU, --ncpu NCPU  number of CPUs. (default: 24)
  --seed SEED           Seed for the Random class (default: None)
  --population_size POPULATION_SIZE
                        Size of replica populations (default: 20)
  --allow_duplicates    Allow the generator to return a molecule which is already stored in the output DB. By default a molecule is mutated until it produces a
                        molecule which is not in the DB yet, and a known molecule is returned only when the molecule has no unknown replacement left.
                        (default: False)
  --no_duplicates       Deprecated, this is the default behaviour now. The option is still accepted so that existing scripts keep working. (default: False)
  --no_contrib          Do not use atom contribution (default: False)

CReM parameters:
  -d fragments.db, --db fragments.db
                        SQLite DB with fragment replacements. (default: None)
  -r RADIUS, --radius RADIUS
                        context radius for replacement. (default: 3)
  --min_freq MIN_FREQ   frequency of occurrence of the fragment in the source database. (default: 0)
  --replace_cycles      look for a replacement of a fragment containing cycles regardless of fragment size. (default: False)
  --max_size MAX_SIZE   maximum number of heavy atoms in a fragment to replace. If it is not given, the CReM default (8) is used. A molecule for which no
                        replacement is found with these parameters is searched once more with replace_cycles enabled, the other parameters are not relaxed.
                        (default: None)
  --max_inc MAX_INC     maximum change in the number of heavy atoms in replacing fragments relative to the number in the replaced one. If it is not given, it is
                        calculated for every molecule from its MW and --mw (the closer to the limit, the smaller the allowed growth). (default: None)
  --min_inc MIN_INC     minimum change in the number of heavy atoms in replacing fragments relative to the number in the replaced one. A negative value means the
                        replacing fragment may be smaller than the replaced one by that number of heavy atoms. If it is not given, it is calculated for every
                        molecule from its MW. (default: None)

Genetic parameters:
  --n_iteration N_ITERATION
                        Number of generations to evolve (5 by default). If you want to continue from the previous last iteration (output DB argument should match the
                        previous run), set the total number of generations you want to perform. If --n_mols is used and this argument is omitted, the number of
                        generations is not limited and the run is stopped by the number of generated molecules only. (default: None)
  --n_mols N_MOLS       Number of generated and successfully docked molecules to be saved in the output DB to stop the run. The run is stopped after the first
                        iteration in which the total number of such molecules in the output DB (molecules of the previous runs on the same DB are counted as well)
                        reaches this value, therefore the final number of molecules can be slightly greater. Molecules which could not be docked are stored but not
                        counted. If --n_iteration is supplied as well, the run is stopped by whichever
                        criterion is reached first. The run is also stopped if no new molecules were saved for the last --n_iter_converged iterations.
                        By default, the run is stopped by the number of generations. (default: None)
  --mutation_rate {1}   Rate of mutation operation. A value below 1 would pass the remaining molecules of a population to the crossover, which is not implemented
                        yet, so only 1 is accepted: every molecule is mutated. (default: 1)
  --elitism             Preserve the best-fitting molecule for the new replicas populations (default: False)
  --scaffold_quota SCAFFOLD_QUOTA
                        In survival mode, probabilistically select at most this many molecules per diversity scaffold when possible. Missing positions are filled from
                        less historically explored scaffolds in the docked DB. Initial seeds take priority and may exceed the quota. Parallel mode is not supported.
                        (default: None)
  --no_diverse_fill     Disable scaffold-aware DB archive filling. Population-external unique molecules are still preferred before recent-pool molecules and copies, but
                        each stage uses fitness alone without scaffold priority or historical/current scaffold penalties. (default: True)
  --archive_refresh_fraction ARCHIVE_REFRESH_FRACTION
                        In survival mode, reserve this fraction of every next population for molecules outside its previous population and current parent/child pool.
                        The number of positions is rounded up. Must be between 0 and 1; 0 disables refresh. (default: 0.0)
  --max_lifetime MAX_LIFETIME
                        To prevent population stagnation, restart a molecule to the initial molecule if it stays unchanged for 20 generations in a row. (default: 20)
  --mode {parallel,survival}
                        GenCReM optimization mode (default: parallel)
  --stop_if_converged   Stop the run when, for the last 5 iterations, the rate of duplicated molecules is >= 0.85 (this value can be changed), meaning the algorithm
                        has already explored local space and cannot find more new solutions. (default: False)
  --convergence_rate CONVERGENCE_RATE
                        Stop the run if --stop_if_converged is used and the rate of duplicated molecules is >= the --convergence_rate value for the last 5 iterations.
                        (default: 0.85)
  --convergence_method {duplication,improvement}
                        Stop the run if --stop_if_converged is used. Duplication method: stop if for the last 5 iterations the duplicate rate in the population
                        is higher than the --convergence_rate argument value. Improvement method: stop if for the last 5 iterations no improvement of docking score was shown.
                        (default: duplication)

Additional molecule parameters:
  --rmsd RMSD           maximum allowed RMSD value relative to a compound to pass to the next iteration. By default, no filtering (default: None)
  --mw MW               maximum ligand molecular weight to pass on the next iteration. (default: 450)
  --rtb RTB             maximum allowed number of rotatable bonds in a compound. (default: 5)
  --logp LOGP           maximum allowed logP of a compound. (default: 4)
  --tpsa TPSA           maximum allowed TPSA of a compound. (default: 120)
  --plif [PLIF ...]     list of protein-ligand interactions compatible with ProLIF. Dot-separated names of each interaction which should be observed for a ligand.
                        Derive these names from a reference ligand. Example: ASP115.HBDonor or ARG34.A.Hydrophobic. Choose interaction type from [Hydrophobic,
                        HBDonor, HBAcceptor, Anionic, Cationic, CationPi, PiCation, FaceToFace, EdgeToFace, MetalAcceptor] (default: None)
  --plif_map [scaled values for each PLIF similarity value: 0 contacts, 1 contact ... any Nth contacts ...]
                        Example: 0 0.5 0.9 1 (default: None)

Easydock parameters:
  --no_tautomerization  disable tautomerization of molecules during protonation (applicable to Chemaxon only). (default: False)
  --no_redock           Do not run redocking for the input SDF conformation. Use the input conformation. (default: False)
  --protonation PROTONATION
                        Choose a protonation program supported by EasyDock. (default: None)
  --protein_h protein.pdb
                        PDB file with the same protein as for docking, but it should have all hydrogens explicit. Required for PLIF detection (--plif) and for the
                        atom contribution calculation, which is enabled unless --no_contrib is used. (default: None)
  --program STRING      name of a docking program supported by EasyDock
  --config FILENAME     YAML file with parameters used by the docking program (e.g., vina.yml or gnina.yml). vina.yml: protein path to a PDBQT file with a protein;
                        protein_setup: path to a text file with binding-site coordinates. (default: None)

Quick Start

gencrem.py -i example/2btr_A_ligand_protected_atoms.sdf -o output.db \
  -d chembl33_f5.db --protein_h example/2btr_A_H.pdb \
  --config example/config_easydock_gnina.yaml \
  --population_size 10 --max_size 10 \
  --seed 1024  --mutation_rate 1 \
  --n_iteration 100 --no_tautomerization \
  --program gnina --protonation molgpka \
  --radius 3 --no_duplicates \
  --mode survival --elitism \
   --stop_if_converged --max_lifetime 15 \
   --convergence_rate 0.9 --convergence_method duplication \
   --no_redock
   

Advanced Features

Protein-ligand interaction fingerprints (ProLIF) generation

To force GenCReM to preserve important contacts, use additional arguments:

--plif leu83.a.hbdonor leu83.a.hbacceptor --plif_map 0 0.5 0.9

--plif_map gives one value per number of observed reference contacts: with two --plif patterns, 0 0.5 0.9 scores a molecule with no contact as 0, with one contact as 0.5 and with both as 0.9. A value of 0 rejects the molecule, so a required minimum of contacts is expressed by leading zeros:

--plif leu83.a.hbdonor leu83.a.hbacceptor --plif_map 0 0 0.9   # both contacts are mandatory

Without --plif_map the PLIF similarity itself (0 to 1) is used as the score.

Preserve the substructure/scaffold of the input molecule

  • Input SDF should not contain hydrogens, or hydrogens should be listed after heavy atoms; otherwise protected IDs can be broken and will not be correctly transferred to child molecules.
  • List atom indices to protect as a protected_user_ids property in the SDF file for each molecule (see example/2btr_A_ligand_protected_atoms.sdf).
  • Indices of preserved atoms should start from 1.
  • Example SDF molecule property:
<protected_user_ids>
3,4,5,6,7,8,19

Stop after a given number of generated molecules

By default the run is stopped after --n_iteration generations. Alternatively, the run can be stopped as soon as the requested number of molecules has been saved in the output DB:

--n_mols 5000 - stop when 5000 generated and docked molecules are stored in the output DB
  • The check is performed at the end of each iteration, therefore the final number of molecules can be slightly greater than the requested one.
  • Only generated molecules with a docking score are counted: input (seed) structures are not, and neither are molecules which could not be docked (they are stored in the DB, just not counted). Molecules generated by the previous runs on the same output DB are counted as well, so a run continued with --n_mols will stop when the DB reaches the total requested number of molecules.
  • If --n_mols is used and --n_iteration is omitted, the number of generations is not limited. If both arguments are supplied, the run is stopped by whichever criterion is reached first.
  • The run is also stopped if no new molecules were saved for the last --n_iter_converged iterations (5 by default), because in this case the requested number of molecules can never be reached. The counter is reset by a single new molecule, so a run which still produces something, even slowly, is not stopped by it.
  • The run is stopped as well when every molecule of the population and every input molecule is a dead end, see Dead-end molecules.
--n_mols 5000 --n_iteration 500 - stop when either 5000 molecules are saved or 500 generations are performed

Preliminary stop mode

Early stop when no new molecules are found for the last N iterations (5 by default), which means the algorithm has already explored local space and cannot find more new solutions

--stop_if_converged - to use preliminary stop mode
--convergence_rate 0.9 - if 90% of new molecules are seen already in the previous iteration  
--convergence_method duplication/improvement (default: duplication)
Methods:
duplication - stop if for the last --n_iter_converged iterations the duplicate rate in the population is higher than the --convergence_rate argument value.
improvement - stop if for the last --n_iter_converged iterations no improvement of docking score was shown.
--n_iter_converged 5 - stop if for the last 5 iterations convergence is reached

Maximum lifetime of a molecule

A molecule which stays in a population without an accepted child is restarted to a randomly chosen input (seed) molecule:

--max_lifetime 15 - let the counter reach 15; restart if the molecule stays again
  • In parallel mode, every retained population position is counted exactly once per iteration, including rejected, missing and undocked children or an iteration without a usable fitness pool.
  • An accepted child starts at 0. A counter which is already at --max_lifetime is restarted on the next iteration in which that molecule remains in the population.
  • A molecule which produced nothing at all is handled as a dead end first, see below.
  • A dead-end molecule is never used as the restart target.
  • If every input seed is a dead end, a lifetime-expired molecule is restarted through the same DB filling procedure as a dead end, without marking the lifetime-expired molecule as dead. The fallback follows the default diverse-fill policy (or ordinary fitness selection with --no_diverse_fill); if no eligible alternative exists, the molecule is retained and its lifetime continues to increase.
  • Seeds are otherwise used explicitly only to construct the initial population. Later survival-pool shortages are filled from the alive, docked DB archive, where seeds remain eligible under the same diversity and fitness weights as every other molecule; they are not forced into the population ahead of other archive candidates.

Note

In --mode survival the molecule preserved by --elitism is deliberately never restarted: the best molecule should be explored around as long as it produces new molecules. --elitism has an effect only in --mode survival.

Identifying input seeds in the output DB

Original molecules supplied as input seeds are already identified by a null parent_id; there is no separate seed column. Select them with:

SELECT * FROM mols WHERE parent_id IS NULL;

Do not use iteration = 0 for this purpose, because molecules generated while constructing the initial population may also belong to iteration 0.

Dead-end molecules

A molecule which generates no new molecule in an iteration has no unknown replacement left in the fragment database for these settings. It is marked as a dead end and replaced in the population, so that it does not occupy a slot in every following iteration. There is nothing to switch on, it is always active.

  • Nothing is deleted. A dead end keeps its docking score, its pose and all its properties in the output DB, it still counts for --n_mols, and it is still reported as the best molecule of the run if it is the best. Only two things change: it is not mutated again, and it is not drawn into a population again.
  • The replacement is a molecule of the output DB, drawn with a probability proportional to its fitness (docking scores scaled with the same softmax the algorithm uses, combined with mol_fitness when --plif or --rmsd is used), among the docked molecules which are not dead ends. Molecules absent from the population and unique simultaneous replacements are used first; copies are used only to fill otherwise unavoidable empty/dead slots.
  • Diverse population filling is enabled by default. Whenever survival selection lacks unique candidates, DB molecules outside the previous population and complete current parent/child pool are preferred. If they are insufficient, other unused DB molecules—including former population members and unselected local candidates—are allowed before copies. Routine deficits use soft diversity: every candidate in a stage remains selectable, with temporary weight fitness / historical_scaffold_count and represented scaffolds weighted by fitness / (historical_scaffold_count * (1 + population_scaffold_count)). Complete local-pool collapse, proactive partial refresh, dead-end replacement and the all-seeds-dead lifetime fallback use hard recovery pressure: absent scaffolds are exhausted before represented scaffolds. Recent-pool fallback and unavoidable copies remain soft. Unreadable rows are skipped and another unique candidate is tried. --no_diverse_fill disables scaffold priority and penalties, but preserves the external-pool-first and unique-before-copy ordering with fitness-only weights. This policy does not change mol_fitness or dead-end state. DEBUG logs report diversity_pressure=soft|hard|fitness_only for survival archive fills and the exact selection stage.
  • Population scaffold quota is enabled with --scaffold_quota N and currently requires --mode survival. During initialization, seeds take priority: every seed is retained when it fits in the population even if the seeds already exceed the quota; generated candidates and then DB archive rows fill the remaining positions under the quota when possible. If there are more seeds than positions, a fitness-weighted seed subset is used and generated/DB candidates are skipped. In later survival selection, the elite counts toward the quota and other parent/child survivors are drawn probabilistically by their temporary selection weights. Missing positions use the same DB filling policy. If the available molecules cannot satisfy the quota, unique quota-violating molecules and finally copies preserve population size, and the violation is logged. With --no_diverse_fill, quota-compliant and then quota-violating DB candidates are weighted only by fitness. The option does not change mol_fitness or retire a scaffold globally. DEBUG logs report seed preservation, survivor skips, archive draws and weights, injections, final scaffold counts, violations and copies.
  • Partial archive refresh is enabled with --archive_refresh_fraction F in survival mode. Every iteration reserves ceil(population_size * F) positions, capped so an elite is retained when --elitism is active. Its primary stage uses eligible, alive and docked molecules outside the complete previous population and current parent/child survival pool. This is population-relative novelty, so a current-iteration molecule from another replica remains eligible. With the default diverse filling, molecules from scaffolds absent from the retained population are selected first; --no_diverse_fill uses fitness-only weighting. If the external pool is insufficient, unused local parent/child candidates are restored first, followed by other unique alive DB molecules, and copies only as the final population-size fallback. --scaffold_quota, when enabled, applies to the combined population; fitness sharing applies only to local parent/child selection weights. DEBUG logs report the requested and reserved positions and each fallback source. The default is 0, which leaves the existing survival procedure unchanged.
  • The run stops when every molecule of the population and every input molecule is a dead end and no docked, non-dead DB replacement remains: the accessible chemical space is exhausted for these settings.
  • The log reports how many molecules were marked in an iteration and how many are dead in total; the end of a run summarizes how many of the generated and of the input molecules are dead ends.

The marks belong to the fragment database they were made with, so they are removed automatically when a run is continued with another -d/--db. A molecule whose mutation ran out of time is marked as well, and because a timeout depends on the machine and not on the molecule, such molecules are listed separately in <output DB>_timeout_mols.log (iteration, id, SMILES, elapsed s, timeout s). If that file is long after a run on a busy machine, those marks can be removed:

sqlite3 output.db "UPDATE mols SET dead_end = 0 WHERE id IN ('001-000023-00', '002-000041-00');"

Use cases

Optimization of a hit. Grow and modify a docked ligand while its well-fitted part is kept:

python gencrem.py -i ligand.sdf -o optimized.db -d fragments_sa2.5.db -r 3 \
  --protein_h protein_H.pdb --config config_vina.yml --program vina \
  --population_size 10 --n_iteration 100 --max_size 10 \
  --mode survival --elitism --max_lifetime 15 -c 32 --seed 1

Scaffold decoration. The same, with a scaffold which must never be modified - list its atom indices as protected_user_ids in the input SDF (see Preserve the substructure/scaffold of the input molecule):

python gencrem.py -i ligand_protected_atoms.sdf -o decorated.db -d fragments_sa2.5.db -r 3 \
  --protein_h protein_H.pdb --config config_vina.yml --program vina \
  --population_size 10 --n_iteration 100 -c 32

De novo generation from fragments. Start from several small molecules instead of one ligand; a SMILES file is enough, the 3D structures are generated and docked:

python gencrem.py -i fragments.smi -o denovo.db -d fragments_sa2.5.db -r 3 \
  --protein_h protein_H.pdb --config config_vina.yml --program vina \
  --population_size 20 --n_mols 5000 --mw 400 --logp 4 -c 32

Keep the key contacts of a reference ligand. Score the molecules by the protein-ligand interactions they reproduce (see ProLIF generation):

python gencrem.py -i ligand.sdf -o plif_guided.db -d fragments_sa2.5.db -r 3 \
  --protein_h protein_H.pdb --config config_vina.yml --program vina \
  --plif leu83.a.hbdonor leu83.a.hbacceptor --plif_map 0 0.5 0.9 \
  --rmsd 2 --population_size 10 --n_iteration 100 -c 32

With --plif_map 0 0.5 0.9 a molecule which reproduces no contact is rejected, one contact is scaled to 0.5 and both to 0.9. --rmsd 2 rejects molecules whose pose moved more than 2 Å away from the pose of their parent.

A fixed number of molecules instead of a fixed number of generations:

python gencrem.py -i ligand.sdf -o run.db -d fragments_sa2.5.db -r 3 \
  --protein_h protein_H.pdb --config config_vina.yml --program vina \
  --population_size 10 --n_mols 1000 -c 32

Return to the TOC

Output

A run writes three files, all named after -o/--output:

file content
output.db SQLite DB with every molecule, its pose and all its properties
output.log the progress of the run (--log to rename it)
output_timeout_mols.log only if molecules were marked as dead ends because their mutation ran out of time

The mols table holds one row per molecule:

column meaning
id iteration-counter-stereoisomer, e.g. 007-000079-00; the input molecules keep their own names
smi, smi_protonated the molecule, and the protonated form which was docked
docking_score the docking score; NULL when the docking failed
mol_block, pdb_block the docked pose
iteration the iteration in which the molecule was generated (0 for the input molecules)
parent_id, parent_original_id the molecule it was generated from, and the input molecule it descends from
mw, rtb, logp, tpsa, qed physicochemical properties
rmsd RMSD of the pose to the pose of the parent (only with --rmsd)
plif_sim similarity of the protein-ligand contacts to the reference ones (only with --plif)
tanimoto similarity to the input molecule it descends from
mol_fitness the combined fitness of the terms above; NULL when neither --plif nor --rmsd is used
protected_user_canon_ids, protected_fragment the atoms which were protected by the user
protected_contrib_canon_ids, mol_atom_contribution_map the atoms which were protected because of their contribution to the docking score, and the contribution of every atom
dead_end 1 when the molecule cannot generate anything new any more
scaffold exact diversity scaffold used by replacement selection; ringless molecules use tagged canonical whole-molecule SMILES

The best molecules of a run:

sqlite3 output.db "SELECT id, smi, docking_score FROM mols
                   WHERE parent_id IS NOT NULL AND docking_score IS NOT NULL
                   ORDER BY docking_score LIMIT 20;"

The first 1000 generated molecules, in the order in which they were generated, and their poses:

sqlite3 -noheader output.db "SELECT id FROM mols
                             WHERE parent_id IS NOT NULL AND docking_score IS NOT NULL
                             ORDER BY id LIMIT 1000;" > ids.txt
python get_sdf.py -i output.db -o first_1000.sdf -d ids.txt

Return to the TOC

Continuing a run

A run is continued by giving the same output DB and no input molecules:

python gencrem.py -o run.db --n_iteration 200 -c 32
  • All settings are restored from the DB, so they cannot change silently. Only --output, --db, --hostfile, --ncpu, --n_iteration, --n_mols and --config may be given again.
  • --n_iteration and --n_mols are the totals of the DB, not additional ones: a DB with 40 molecules and --n_mols 100 generates 60 more.
  • The molecules of the previous runs are known to the generator, so they are not generated again.
  • New databases checkpoint every population position and its exact lifetime after each completed population selection. A continued run restores the latest checkpoint, including duplicate positions and their independent counters. Output DBs created before exact population checkpointing are not supported. RNG state and an iteration interrupted before its population checkpoint are not restored, so continuation is not bit-for-bit deterministic.
  • If another fragment database is given (-d/--db), the dead-end marks are removed, because the molecules can have replacements again.

Return to the TOC

Notes and limitations

  • CReM version. Use crem==0.2.17, see the note in Installation. With crem>=0.3 the protected atoms of a molecule are not transferred to its children.
  • Crossover is not implemented. --mutation_rate accepts only 1, so every molecule of a population is mutated.
  • One population per run. --population_replicas accepts only 1; run several jobs with different --seed for replicas.
  • Reproducibility. --seed seeds the genetic algorithm, but the mutation shuffles its candidates with its own generator and the docking runs in parallel, so two runs with the same seed can differ.
  • --plif and --rmsd are the only fitness terms; without them the fitness is the scaled docking score alone and mol_fitness stays NULL.

Return to the TOC

References

  1. Polishchuk, P., CReM: Chemically reasonable mutations framework for structure generation, Journal of Cheminformatics, 2020, 12, 1, 1-18.

Return to the TOC

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages