GenCReM: molecule optimization, scaffold decoration, de novo generation guided by explainable docking
- Features
- How a run works
- Installation
- Usage
- Advanced Features
- Use cases
- Output
- Continuing a run
- Notes and limitations
- References
- 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
One iteration of the genetic algorithm:
- 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_incand--min_inc. - 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. - Docking. The new molecules are docked with EasyDock (
--program,--config), optionally after protonation (--protonation) and tautomer generation. - Atom contributions. Unless
--no_contribis 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. - 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. - Selection. In
--mode parallelevery molecule competes with its own child; in--mode survivalthe whole population is drawn from the parents and their children by fitness, optionally keeping the best molecule (--elitism). - 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_lifetimeiterations 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.
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.3builds mutated molecules withmolzipinstead of RDKit reactions, so the products no longer carry thereact_atom_idxproperty. 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.
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)
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
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.
- 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_idsproperty in the SDF file for each molecule (seeexample/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
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_molswill stop when the DB reaches the total requested number of molecules. - If
--n_molsis used and--n_iterationis 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_convergediterations (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
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
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_lifetimeis 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.
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.
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_fitnesswhen--plifor--rmsdis 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_countand represented scaffolds weighted byfitness / (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_filldisables scaffold priority and penalties, but preserves the external-pool-first and unique-before-copy ordering with fitness-only weights. This policy does not changemol_fitnessor dead-end state. DEBUG logs reportdiversity_pressure=soft|hard|fitness_onlyfor survival archive fills and the exact selection stage. - Population scaffold quota is enabled with
--scaffold_quota Nand 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 changemol_fitnessor 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 Fin survival mode. Every iteration reservesceil(population_size * F)positions, capped so an elite is retained when--elitismis 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_filluses 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 is0, 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');"
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
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
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_molsand--configmay be given again. --n_iterationand--n_molsare the totals of the DB, not additional ones: a DB with 40 molecules and--n_mols 100generates 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.
- CReM version. Use
crem==0.2.17, see the note in Installation. Withcrem>=0.3the protected atoms of a molecule are not transferred to its children. - Crossover is not implemented.
--mutation_rateaccepts only 1, so every molecule of a population is mutated. - One population per run.
--population_replicasaccepts only 1; run several jobs with different--seedfor replicas. - Reproducibility.
--seedseeds 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. --plifand--rmsdare the only fitness terms; without them the fitness is the scaled docking score alone andmol_fitnessstays NULL.
- Polishchuk, P., CReM: Chemically reasonable mutations framework for structure generation, Journal of Cheminformatics, 2020, 12, 1, 1-18.