fragmenstein.monster package
- class fragmenstein.Monster(hits: List[Mol], average_position: bool = False, joining_cutoff: float = 5, random_seed: int | None = None)[source]
Bases:
_MonsterFF,_MonsterPlace,_MonsterCombineThis creates a stitched together monster. For initilialisation for either placing or combining, it needs a list of hits (rdkit.Chem.Mol).
Note, the hits have to be 3D embedded as present in the protein —it would defeat the point otherwise! For a helper method to extract them from crystal structures see Victor.extract_mol.
The calculation are done either by place or merge.
## Place
>>> monster.place(mol)
Given a RDKit molecule and a series of hits it makes a spatially stitched together version of the initial molecule based on the hits. The reason is to do place the followup compound to the hits as faithfully as possible regardless of the screaming forcefields.
.mol_optionsare the possible equiprobable alternatives..positioned_molis the desired output (rdkit.Chem.Mol object).initial_molis the input (rdkit.Chem.Mol object), this is None in a .combine call..modifications['scaffold']is the combined version of the hits (rdkit.Chem.Mol object)..modifications['chimera']is the combined version of the hits, but with differing atoms made to match the followup (rdkit.Chem.Mol object).
.get_positional_mapping, which works also as a class method, creates a dictionary of mol_A atom index to mol_B atom index based on distance (cutoff 2Å) and not MCS.The code works in two broad steps, first a scaffold is made, which is the combination of the hits (by position). Then the followup is placed. It is not embedded with constrained embedding functionality of RDKit as this requires the reference molecule to have a valid geometry, which these absolutely do not have this. Novel side chains are added by aligning an optimised conformer against the closest 3-4 reference atoms. Note that
.initial_molis not touched..positioned_molmay have lost some custom properties, but the atom indices are the same.If an atom in a Chem.Mol object is provided via
attachmentargument and the molecule contains a dummy atom. Namely element R in mol file or * in string.## Combine
>>> monster.combine(keep_all=True, collapse_rings=True, joining_cutoff= 5))
Combines the hits by merging and linking.
collapse_ringsargument results in rings being collapsed before merging to avoid oddities. The last step within the call is fixing any oddities of impossible chemistry via the callrectify. This uses the separate classRectifierto fix it.## Attributes
Common input derived
- Variables:
hits (list)
throw_on_discard (bool) – filled by keep_all
Common derived
- Variables:
matched (List[str]) – (dynamic) accepted hit names
unmatched (List[str]) – discarded hit names
journal (Logger) – The “journal” is the log of Dr Victor Frankenstein (see Victor for more)
modifications (dict) – copies of the mols along the way
mol_options (list) – equally valid alternatives to self.positioned_mol
placespecific:- Variables:
positioned_mol (Mol)
attachment (NoneType)
initial_mol (NoneType)
average_position (bool)
num_common (int) – (dynamic) number of atoms in common between follow-up and hits
percent_common (float) – (dynamic) percentage of atoms of follow-up that are present in the hits
combinespecific:- Variables:
joining_cutoff (int) – how distant (in Å) is too much?
atoms_in_bridge_cutoff (int) – how many bridge atoms can be deleted? (0 = preserves norbornane, 1 = preserves adamantane)
Class attributes best ignored:
- Variables:
closeness_weights (list) – list of functions to penalise closeness (ignore for most applications)
dummy (Mol) – The virtual atom where the targets attaches. by default *. Best not override.
dummy_symbol (str) – The virtual atom where the targets attaches. by default *. Best not override.
matching_modes (list)
- MMFF_score(mol: Mol | None = None, delta: bool = False, mode: str = 'MMFF') float
Merck force field. Chosen over Universal for no reason at all.
- Parameters:
mol (
Chem.Moloptional. If absent extracts from pose.) – liganddelta (bool) – report difference from unbound (minimized)
mode (str) – ‘MMFF’ or ‘UFF’
- Returns:
kcal/mol
- Return type:
float
- Warning:
This was moved out of Igor. Victor has the method for calling it with igor.mol_from_pose
- __init__(hits: List[Mol], average_position: bool = False, joining_cutoff: float = 5, random_seed: int | None = None)
Initialisation starts Monster, but it does not do any mergers or placements. This is changed in revision 0.6 (previously mol was specified for the latter)
- Parameters:
hits
average_position
joining_cutoff – joining cutoff used in “full” mode
random_seed – A random seed for rdkit embedding calculations during placement
- atoms_in_bridge_cutoff = 2
- by_expansion(primary_name: str | None = None, min_mode_index: int = 0) Mol
Get the maps. Find the map with the most atoms covered. Use that map as the base map for the other maps.
- closeness_weights = [(<function _MonsterCommunal._closest__is_warhead_marked>, nan), (<function _MonsterCommunal._closest__is_fullbonded>, 1.0), (<function _MonsterCommunal._closest__is_ring_atom>, 0.5)]
- collapse_mols(mols: List[Mol])
- collapse_ring(mol: Mol) Mol
Collapses a ring(s) into a single dummy atom(s). Stores data as JSON in the atom.
- Parameters:
mol
- Returns:
- combine(keep_all: bool = True, collapse_rings: bool = True, joining_cutoff: int = 5)
Merge/links the hits. (Main entrypoint)
- Parameters:
keep_all
collapse_rings
joining_cutoff
- Returns:
- convert_origins_to_custom_map(mol: Mol | None = None, forbiddance=True) Dict[str, Dict[int, int]]
The origins stored in the followup differ in format from the custom_map. The former is a list of lists of hit_name+atom_index, while the latter is a dictionary of hit_name to dictionary of hit atom indices to _intended_ followup index. This method converts the former to the latter. If forbiddance is True, non mapping atoms are marked with negatives.
If mol is None, then self.positioned_mol is used.
- Returns:
- cutoff = 2
- draw_nicely(mol, show=True, **kwargs) MolDraw2DSVG
Draw with atom indices for Jupyter notebooks.
- Parameters:
mol
kwargs – Key value pairs get fed into
PrepareAndDrawMolecule.
- Returns:
- dummy = <rdkit.Chem.rdchem.Mol object>
The virtual atom where the targets attaches
- dummy_symbol = '*'
- expand_custom_map(custom_map: Dict[str, Dict[int, int]], addend: Dict[str, Dict[int, int]]) Dict[str, Dict[int, int]]
- expand_ring(mol: Mol) Mol
Undoes collapse ring
- Parameters:
mol – untouched.
- Returns:
- classmethod extract_atoms(protein: Mol, keepers: List[int], expand_aromatics: bool = True) Mol
Extract the given atom indices (
keepers) fromprotein. Expanding to full aromatic ring and copying conformers
- extract_from_neighborhood(system: Mol) Mol
Given a system of a neighbourhood + ligand extract everything that is not marked
IsNeighborhood.
- fix_custom_map(custom_map: Dict[str, Sequence[Tuple[int, int]] | Dict[int, int]]) Dict[str, Dict[int, int]]
This is duplicated in SpecialCompareAtoms, but will be deprecated in favour of this one.
Make sure its Dict[str, Dict[int, int]]
There is a bit of confusion about the custom map. Converts the custom map from dict of lists of 2-element tuples to dict of dicts.
- fix_hits(hits: List[Mol]) List[Mol]
Adds the
_NameProp if needed asserts everything is a Chem.Mol callsstore_positions:param hits: :return:
- full_blending() None
a single scaffold is made (except for
.unmatched)
- get_atom_map_fromProp(mol)
- classmethod get_best_scoring(mols: List[RWMol]) Mol
Sorts molecules by how well they score w/ Merch FF
- classmethod get_close_indices(query: Mol, target: Mol, cutoff: float = 5.0) List[int]
Give an rdkit Chem.Mol
queryget the atom idices oftargetthat are withcutoffÅ.
- get_color_origins() Dict[str, Dict[int, str]]
Get for the hits and followup the color of the origin as seen in show_comparison :return:
- classmethod get_combined_rmsd(followup_moved: Mol, followup_placed: Mol | None = None, hits: List[Mol] | None = None) float
Depracated. The inbuilt RMSD calculations in RDKit align the two molecules, this does not align them. This deals with the case of multiple hits. For euclidean distance the square root of the sum of the differences in each coordinates is taken. For a regular RMSD the still-squared distance is averaged before taking the root. Here the average is done across all the atom pairs between each hit and the followup. Therefore, atoms in followup that derive in the blended molecule by multiple atom are scored multiple times.
As a classmethod
followup_placedandhitsmust be provided. But as an instance method they don’t.- Parameters:
followup_moved – followup compound moved by Igor or similar
followup_placed – followup compound as placed by Monster
hits – list of hits.
- Returns:
combined RMSD
- get_hit_by_name(name: str) Mol
Given a name of a hit (as defined in
_Nameproperty), return the hit. Do note fix_hits will have been called, so the name may be assigned. :param name: :return:
- get_largest_fragment(mol)
- get_legend(show_positioned_mol: bool = True) str
- get_mcs_mapping(hit, followup, min_mode_index: int = 0) Tuple[Dict[int, int], dict]
This is a weird method. It does a strict MCS match. And then it uses laxer searches and finds the case where a lax search includes the strict search.
- Parameters:
hit – query molecule
followup – target/ref molecule
min_mode_index – the lowest index to try (opt. speed reasons)
- Returns:
mapping and mode
- get_mcs_mappings(hit: Mol, followup: Mol, min_mode_index: int = 0, custom_map: Dict[str, Dict[int, int]] | None = None) Tuple[List[Dict[int, int]], ExtendedFMCSMode]
This is a curious method. It does a strict MCS match. And then it uses laxer searches and finds the case where a lax search includes the strict search.
- Parameters:
hit – query molecule
followup – target/ref molecule
min_mode_index – the lowest index to try (opt. speed reasons)
custom_map – is the user defined hit name to list of tuples of hit and followup index pairs
- Returns:
mappings and mode
- get_neighborhood(apo_block: str, cutoff: float, mol: Mol | None = None, addHs=True) Mol
Get the neighborhood of the protein from the apo_block around the cutoff of the mol. Note: The atoms will have a prop
IsNeighborhoodwhich is used after it is combined.
- classmethod get_pair_rmsd(molA, molB, mapping: List[Tuple[int, int]]) float
- classmethod get_positional_mapping(mol_A: Mol, mol_B: Mol, dummy_w_dummy=True) Dict[int, int]
Returns a map to convert overlapping atom of A onto B Cutoff 2 Å (see class attr.)
- guess_origins(mol: Mol = None, hits: List[Mol] | None = None)
Given a positioned mol guess its origins…
- Parameters:
mol
- Returns:
- static inspect_amide_torsions(mol)
The most noticeable torsions are the amide ones. This is to describe what is happening.
- join_neighboring_mols(mol_A: Mol, mol_B: Mol)
Joins two molecules by first calling _find_closest to find closest. That method does all the thinking. then by calling _join_atoms.
- Parameters:
mol_A
mol_B
:return:Ï
- journal = <Logger Fragmenstein (DEBUG)>
- keep_copies(mols: List[Mol], label=None)
- keep_copy(mol: Mol, label=None)
- property linker_atom_zahl
Getter for linker_atom_zahl To change set
linker_elementclass property.
- linker_element = 'O'
- make_chimera(template: Mol, min_mode_index=0) Mol
This is to avoid extreme corner corner cases. E.g. here the MCS is ringMatchesRingOnly=True and AtomCompare.CompareAny, while for the positioning this is not the case.
Called by full and partial blending modes.
- Returns:
- make_ideal_mol(mol: Mol | None = None, ff_minimise: bool = False) Mol
- make_pse(filename='test.pse', extra_mols: Iterable[Mol] | None = None)
This is specifically for debugging the full fragment merging mode. For general use. Please use the Victor method
make_pse.- Parameters:
filename
- Returns:
- property matched: List[str]
This is the counter to unmatched. It’s dynamic as you never know…
- Returns:
- matching_modes = [{'atomCompare': rdkit.Chem.rdFMCS.AtomCompare.CompareAny, 'bondCompare': rdkit.Chem.rdFMCS.BondCompare.CompareAny, 'ringCompare': rdkit.Chem.rdFMCS.RingCompare.PermissiveRingFusion, 'ringMatchesRingOnly': False}, {'atomCompare': rdkit.Chem.rdFMCS.AtomCompare.CompareAny, 'bondCompare': rdkit.Chem.rdFMCS.BondCompare.CompareOrder, 'ringCompare': rdkit.Chem.rdFMCS.RingCompare.PermissiveRingFusion, 'ringMatchesRingOnly': False}, {'atomCompare': rdkit.Chem.rdFMCS.AtomCompare.CompareElements, 'bondCompare': rdkit.Chem.rdFMCS.BondCompare.CompareOrder, 'ringCompare': rdkit.Chem.rdFMCS.RingCompare.PermissiveRingFusion, 'ringMatchesRingOnly': False}, {'atomCompare': rdkit.Chem.rdFMCS.AtomCompare.CompareAny, 'bondCompare': rdkit.Chem.rdFMCS.BondCompare.CompareAny, 'ringCompare': rdkit.Chem.rdFMCS.RingCompare.PermissiveRingFusion, 'ringMatchesRingOnly': True}, {'atomCompare': rdkit.Chem.rdFMCS.AtomCompare.CompareAny, 'bondCompare': rdkit.Chem.rdFMCS.BondCompare.CompareOrder, 'ringCompare': rdkit.Chem.rdFMCS.RingCompare.PermissiveRingFusion, 'ringMatchesRingOnly': True}, {'atomCompare': rdkit.Chem.rdFMCS.AtomCompare.CompareElements, 'bondCompare': rdkit.Chem.rdFMCS.BondCompare.CompareOrder, 'ringCompare': rdkit.Chem.rdFMCS.RingCompare.PermissiveRingFusion, 'ringMatchesRingOnly': True}]
- max_from_mol(mol: Mol = None)
- merge_pair(scaffold: Mol, fragmentanda: Mol, mapping: Optional = None) Mol
To specify attachments use
.merge. To understand what is going on see.categorize- Parameters:
scaffold – mol to be added to.
fragmentanda – mol to be fragmented
mapping – see
get_positional_mapping. Optional in _pre_fragment_pairs
- Returns:
- merge_pairing_lists(nonunique_pairs: List[Tuple[Atom, Atom]], ringcore_first=True) List[Tuple[Atom, Atom]]
- mmff_minimize(mol: Mol | None = None, neighborhood: Mol | None = None, ff_max_displacement: float = 0.0, ff_constraint: int = 10, ff_max_iterations: int = 200, ff_cutoff: float = 100.0, allow_lax: bool = True, prevent_cis: bool = True) MinizationOutcome
Minimises a mol, or self.positioned_mol if not provided, with MMFF constrained to ff_max_displacement Å. Gets called by Victor if the flag .monster_mmff_minimisation is true during PDB template construction.
- Parameters:
mol – Molecule to minimise. If None, self.positioned_mol is used.
neighborhood – Protein neighboorhood (ignored if None)
ff_max_displacement – Distance threshold (Å) for atomic positions mapped to hits for MMFF constrains. if NaN then fixed point constraints (no movement) are used. This is passed as maxDispl to MMFFAddPositionConstraint.
ff_constraint – Force constant for MMFF constraints.
ff_cutoff – kcal/mol diff value to consider a failed minimisation.
allow_lax – If True and the minimisation fails, the constraints are halved and the minimisation is rerun.
- Returns:
None
Note that most methods calling this via Victor now use its
.settings['ff_max_displacement']and.settings['ff_constraint']and do not use the defaults.
- no_blending(broad=False) None
no merging is done. The hits are mapped individually. Not great for small fragments.
- property num_common: int
- offset(mol: Mol)
This is to prevent clashes. The numbers of the ori indices stored in collapsed rings are offset by the class variable (_collapsed_ring_offset) multiples of 100. (autoincrements to avoid dramas)
- Parameters:
mol
- Returns:
- origin_from_mol(mol: Mol = None)
these values are stored from Monster for scaffold, chimera and positioned_mol See make_chimera or place_from_map for more info on _Origin
- Parameters:
mol – Chem.Mol
- Returns:
stdev list for each atom
- partial_blending() None
multiple possible scaffolds for placement and best is chosen
- partially_blend_hits(hits: List[Mol] | None = None) List[Mol]
This is the partial merge algorithm, wherein the hits are attempted to be combined. If the combination is bad. It will not be combined. Returning a list of possible options. These will have the atoms changed too.
- Parameters:
hits
distance
- Returns:
- property percent_common: int
- pick_best() Tuple[Mol, int]
Method for partial merging for placement
- Returns:
unrefined_scaffold, mode_index
- place(mol: Mol, attachment: Mol | None = None, custom_map: Dict[str, Dict[int, int]] | None = None, merging_mode: str = 'expansion', enforce_warhead_mapping: bool = True, primary_name=None)
Positioned a given mol based on the hits. (Main entrypoint) accepts the argument merging_mode, by default it is “expansion”, but was “permissive_none”, which call .by_expansion and .no_blending(broad=True) respectively. “off” (does nothing except fill the attribute
initial_mol), “full” (.full_blending()), “partial” (.partial_blending()) and “none” (.no_blending(), but less thorough) are accepted.- Parameters:
mol
attachment – This the SG of the cysteine if covalent
custom_map – Dict of hit_name to Dict of hit_idx to followup_idx
merging_mode
primary_name – override the name of the primary hit if merging_mode is ‘expansion’
- Returns:
- place_from_map(target_mol: Mol, template_mol: Mol, atom_map: Dict | None = None, random_seed=None) Mol
This method places the atoms with known mapping and places the ‘uniques’ (novel) via an aligned mol (the ‘sextant’) This sextant business is a workaround for the fact that only minimised molecules can use the partial embedding function of RDKit.
The template molecule may be actually two or more fragments, as happens for the no blending mode. In RDKit, the fragments within a “molecule” are not connected, but have sequential atom indices.
- Parameters:
target_mol – target mol
template_mol – the template/scaffold to place the mol
atom_map – something that get_mcs_mapping would return.
- Returns:
- place_smiles(smiles: str, long_name: str | None = None, **kwargs)
- post_ff_addition_step(mol: ~rdkit.Chem.rdchem.Mol, ff: <module 'rdkit.ForceField' from '/home/docs/checkouts/readthedocs.org/user_builds/fragmenstein/envs/latest/lib/python3.11/site-packages/rdkit/ForceField/__init__.py'>)
THis is an empty method for user created subclasses to add their own constraints to the MMFF minimisation.
- posthoc_refine(scaffold: Mol, indices: List[int] | None = None) Mol
Given a scaffold and a list of indices, refine the scaffold.
- Parameters:
scaffold
indices – if absent, use all atoms
- Returns:
- pretweak() None
What if the fragments were prealigned slightly? Really bad things happen. Nothing currently uses this without user interverntion.
- Returns:
- propagate_alternatives(fewer: List[Mol]) int
Given the alt atoms strored in the Chem.Atom property
_AltSymboltry those
- rectify()
- static renumber_followup_custom_map(original_mol: Mol, new_mol: Mol, custom_map: Dict[str, Dict[int, int]]) Dict[str, Dict[int, int]]
Give a followup
original_moland a copy but with its atom indices changed return a new map for the copy
- sample_new_conformation(random_seed=None)
This method is intended for Multivictor. It generates a new conformation based on different random seeds.
- save_commonality(filename: str | None = None)
Saves an SVG of the followup fragmenstein monster with the common atoms with the chimeric scaffold highlighted.
- Parameters:
filename – optinal filename to save it as. Otherwise returns a Draw.MolDraw2DSVG object.
- Returns:
- save_temp(mol)
This is a silly debug-by-print debug method. drop it in where you want to spy on stuff.
- static score_mol(mol: Mol) float
Scores a mol without minimising
- show(to_display: bool = False, show_positioned_mol: bool = True, viewer_mode='rdkit') view' id='133176890420560'>, str]
generates a
NGLWidgetor apy3Dmol.viewdepending onviewer_mode, which is set by default to what’s installed. With the compounds and the merger if present. To override the colours: The colours will be those in theChem.Mol’s property_colorif present.to_display if True will display the legend and the viewer. (
IPython.display.displaywill show them too)Returns -> nv.NGLWidget
- show_comparison(*args, **kwargs)
” Show the atom provenance of the follow molecule.
Parameters:
nothing -> uses self.origin_from_mol
hit2followup -> uses the hit2followup dict
- simply_merge_hits(hits: List[Mol] | None = None, linked: bool = True) Mol
Recursively stick the hits together and average the positions. This is the monster of automerging, full-merging mapping and partial merging mapping. The latter however uses partially_blend_hits first. The hits are not ring-collapsed and -expanded herein.
- Parameters:
hits – optionally give a hit list, else uses the attribute
.hits.linked – if true the molecules are joined, else they are placed in the same molecule as disconnected fragments.
- Returns:
the rdkit.Chem.Mol object that will fill
.scaffold
- stdev_from_mol(mol: Mol = None)
these values are stored from Monster for scaffold, chimera and positioned_mol
- Parameters:
mol – Chem.Mol
- Returns:
stdev list for each atom
- store_origin_colors_atomically()
Store the color of the origin in the mol as the private property _color :return:
- store_positions(mol: Mol) Mol
Saves positional data as _x, _y, _z and majorly
_ori_i, the original index. The latter gets used by_get_new_index.- Parameters:
mol
- Returns:
- strict_matching_mode = {'atomCompare': rdkit.Chem.rdFMCS.AtomCompare.CompareElements, 'bondCompare': rdkit.Chem.rdFMCS.BondCompare.CompareOrder, 'matchChiralTag': True, 'ringCompare': rdkit.Chem.rdFMCS.RingCompare.StrictRingFusion, 'ringMatchesRingOnly': True}
- throw_on_discard = False
- to_3Dmol(show_positioned_mol: bool = True, *args, **kwargs) <Mock name='py3Dmol.view' id='133176890420560'>
User: you probably want to use show() instead… unless you have both ngl and py3Dmol installed.
This is called by both
Monster.to_3DmolandVictor.to_3DmolThe
argsandkwargsdo nothing
- to_nglview(show_positioned_mol: False, *args, **kwargs) <Mock name='MolNGLWidget' id='133176890126032'>
User: you probably want to use show() instead… unless you have both ngl and py3Dmol installed.
This is called by both
Monster.to_nglviewandVictor.to_nglviewThe color can be dictated by the optional private property_color, which may have been assigned bywalton.color_in()or the user.The
argsandkwargsdo nothing- Returns:
- transfer_ring_data(donor: Atom, acceptor: Atom)
Transfer the info if a ringcore atom.
- Parameters:
donor
acceptor
- Returns:
fragmenstein.monster.bond_provenance module
- class fragmenstein.monster.BondProvenance(value)[source]
Bases:
EnumWhere does the bond come from. This is used to keep names consistent… For now original is used in places. The others are interchangeable TBH.
- LINKER = 4
- MAIN_NOVEL = 2
- ORIGINAL = 1
- OTHER_NOVEL = 3
- UNASSIGNED = 5
- classmethod get_bond(bond: Bond) BondProvenance[source]
- classmethod get_bonds(bonds: List[Bond]) List[BondProvenance][source]
fragmenstein.monster.positional_mapping module
- class fragmenstein.monster.GPM[source]
Bases:
objectThis class simply contains
get_positional_mappingand is inherited both by Monster and Unmerge.get_positional_mappingteturns a map to convert overlapping atom of A onto B- __init__()
- cutoff = 2
fragmenstein.monster.unmerge_mapper module
- class fragmenstein.monster.Unmerge(followup: Mol, mols: List[Mol], maps: Dict[str, List[Dict[int, int]]], no_discard: bool = False)[source]
Bases:
GPMThis class tries to solve the mapping problem by try all possible mappings of the target to the ligand. It is one of three in Monster (full merge, partial merge, unmerge.
It is great with fragments that do not connect, but is bad when a hit has a typo.
the positions must overlap if any atom is mapped in two maps
no bond can be over 3 A
The chosen map
combined_mapis a dict that goes fromfollowupmol tocombinedmol which is the hits in a single molecule.Note that some molecules are discarded entirely.
- __init__(followup: Mol, mols: List[Mol], maps: Dict[str, List[Dict[int, int]]], no_discard: bool = False)[source]
At the minute maps is a dict of hit name to a list of possible maps, wherein each map is a dict of atom index in the followup molecule to atom index in the target molecule, not the reverse as it will be soon… (see
mcs_mapping)- Parameters:
followup (Chem.Mol) – the molecule to place
mols (List[Chem.Mol]) – 3D molecules
maps (Dict[str, List[Dict[int, int]]]) – can be generated outseide of Monster by
.make_mapsno_discard – do not allow any to be discarded
- cutoff = 2
- distance_cutoff = 3
how distance is too distant in Å
- get_key(d: dict, v: Any)[source]
Given a value and a dict and a value get the key. :param d: :param v: :return:
- classmethod get_positional_mapping(mol_A: Mol, mol_B: Mol, dummy_w_dummy=True) Dict[int, int]
Returns a map to convert overlapping atom of A onto B Cutoff 2 Å (see class attr.)
- get_possible_map(other: Mol, label: str, o_map: Dict[int, int], inter_map: Dict[int, int], combined: Mol, combined_map: Dict[int, int]) Dict[int, int][source]
This analyses a single map (o_map) and returns a possible map
- Parameters:
other
label
o_map – followup -> other
inter_map
combined
combined_map – followup -> combined
- Returns:
followup -> other
- goodness_sorter_factory(offness_weight: int = 3) Callable[source]
This is a factory for symmetry with template sorter… there is zero other reason for it to be so.
- judge_n_move_on(combined, combined_map, other, possible_map, others, disregarded)[source]
The mutables need to be within their own scope
- Parameters:
combined
combined_map
other
possible_map
others
disregarded
- Returns:
- classmethod make_maps(target: Mol, mols: List[Mol], mode: Dict[str, Any] | None = None) Dict[str, List[Dict[int, int]]][source]
This is basically if someone is using this class outside of Monster
Returns a dictionary of key mol name and value a list of possible dictionary with index of an atom in target mol to the index given mol. Note that a bunch of mapping modes can be found in Monster init mixin class.
- Parameters:
target – the molecule to be mapped
mols – the list of molecules with positional data to be mapped to
mode – dict of setting for MCS step
- Returns:
- max_strikes = 3
number of discrepancies tollerated.
- measure_map(mol: Mol, mapping: Dict[int, int]) array[source]
Returns a vector with the distances but not of length len(mapping) This used by offness to score how bad the mapping is
- Parameters:
mol
mapping – followup to comined
- Returns:
- offness(mol: Mol, mapping: Dict[int, int], cutoff_distance: float = 2.5) int[source]
How many bonds are too long?
- Parameters:
mol
mapping
- Returns:
- pick = -1
- rotational_approach = True
- store(combined: Mol, combined_map: Dict[int, int], disregarded: List[Mol])[source]
Stores combined molecule and its map into the instance.
- template_sorter_factory(accounted_for) Callable[source]
returns the number of atoms that have not already been accounted for.
- unmerge_inner(combined: Mol, combined_map: Dict[int, int], others: List[Mol], disregarded: List[Mol]) None[source]
Assesses a combination of maps rejections: unmapped (nothing maps) / unnovel (adds nothing)
Do note that this method uses a lot of instance attributes.
self.mapshas the mapping data. This method combines to makeself.combined_map.- Parameters:
combined
combined_map – This is passed empty the first time.
others – It’s a list of a deque that is rotated (if rotational_approach is True) of self.mols
disregarded
- Returns:
fragmenstein.monster.mcs_mapping module
- class fragmenstein.monster.SpecialCompareAtoms(comparison: AtomCompare = rdkit.Chem.rdFMCS.AtomCompare.CompareAnyHeavyAtom, custom_map: Dict[str, Dict[int, int]] | None = None, exclusive_mapping: bool = True)[source]
Bases:
VanillaCompareAtomsThis works like the
_get_atom_mapsdid prior to Fragmentein version 0.9. The mapping as discussed in GitHub issue #23 is in the formatmapping = { ‘hit1’: {1:1,2:5} ‘hit2’: {3:3,4:4,4:6}}
The hit index is first, followup index is the second. The index -1 for a followup index is the same as not providing the hit index, it is described here solely for clarity not for use.
mapping = { ‘hit1’: {1:1,2:5, 3:-1} ‘hit2’: {3:3,4:4,4:6}}
The index -2 for a followup index will result in the hit atom index not matching any followup index.
mapping = { ‘hit1’: {1:1,2:5, 3:-2} ‘hit2’: {3:3,4:4,4:6}}
If
exclusive_mappingargument of __init__ is True, then if a followup index is present in one hit, but not in a second hit, then no atom of the second hit will match that followup atom. A negative index for a hit atom index means that no atom in that hit will match the corresponding followup index.mapping = { ‘hit1’: {1:1,2:5,-1:3, -2: 7} ‘hit2’: {3:3,4:4,4:6}}
However, a positive integer on a different hit overrides it, therefore, in the above followup atom 3 cannot be matched to any atom in hit1, but will match atom 3 in hit2. Followup atom 7 will not match either.
SpecialCompareAtoms(custom_map=mapping, exclusive_mapping=True)
- CheckAtomCharge((MCSAtomCompare)self, (MCSAtomCompareParameters)parameters, (Mol)mol1, (int)atom1, (Mol)mol2, (int)atom2) bool :
Return True if both atoms have the same formal charge
- C++ signature :
bool CheckAtomCharge(RDKit::PyMCSAtomCompare {lvalue},RDKit::MCSAtomCompareParameters,RDKit::ROMol,unsigned int,RDKit::ROMol,unsigned int)
- CheckAtomChirality((MCSAtomCompare)self, (MCSAtomCompareParameters)parameters, (Mol)mol1, (int)atom1, (Mol)mol2, (int)atom2) bool :
Return True if both atoms have, or have not, a chiral tag
- C++ signature :
bool CheckAtomChirality(RDKit::PyMCSAtomCompare {lvalue},RDKit::MCSAtomCompareParameters,RDKit::ROMol,unsigned int,RDKit::ROMol,unsigned int)
- CheckAtomRingMatch((MCSAtomCompare)self, (MCSAtomCompareParameters)parameters, (Mol)mol1, (int)atom1, (Mol)mol2, (int)atom2) bool :
Return True if both atoms are, or are not, in a ring
- C++ signature :
bool CheckAtomRingMatch(RDKit::PyMCSAtomCompare {lvalue},RDKit::MCSAtomCompareParameters,RDKit::ROMol,unsigned int,RDKit::ROMol,unsigned int)
- __init__(comparison: AtomCompare = rdkit.Chem.rdFMCS.AtomCompare.CompareAnyHeavyAtom, custom_map: Dict[str, Dict[int, int]] | None = None, exclusive_mapping: bool = True)[source]
Whereas the atomCompare is an enum, this is a callable class. But in parameters there is no compareElement booleans etc. only Isotope… In https://github.com/rdkit/rdkit/blob/master/Code/GraphMol/FMCS/Wrap/testFMCS.py it is clear one needs to make one’s own.
- fix_custom_map(custom_map: Dict[str, Sequence[Tuple[int, int]] | Dict[int, int]]) Dict[str, Dict[int, int]][source]
This will be deprecated in the future. As Monster.fix_custom_map is better.
Make sure its Dict[str, Dict[int, int]]
There is a bit of confusion about the custom map. Converts the custom map from dict of lists of 2-element tuples to dict of dicts.
- get_custom(hit_mol: Mol, hit_atom_idx: int) int[source]
What idx of followup corresponds to the
hit_atom_idxindex ofhit_mol? If nothing, -1 is returned
- get_valid_matches(parameters: MCSAtomCompareParameters, common: Mol, hit: Mol, followup: Mol) List[Dict[int, int]][source]
- get_valid_matches(parameters: MCSParameters, common: Mol, hit: Mol, followup: Mol) List[IndexMap]
Returns a list of possible matches, each a dictionary of hit to follow indices, that obey the criteria of the atomic comparison. (Formerly this was a IndexAtom)
This however does not check if all the atoms in custom are present. For that,
Monster._validate_vs_customis called in the methodMonster.get_mcs_mappings, after callingMonster._get_atom_maps, which calls this method. (Monster.get_mcs_mappingstries different matching schema, whileMonster._get_atom_mapsis for one single scheme). The primary reason why this is so, is that there are two tiers of requirements:The custom map must be present vs
The custom map may be present, but has to be obeyed.
parameters can be rdFMCS.MCSAtomCompareParameters or rdFMCS.MCSParameters
- class fragmenstein.monster.IndexMap
Sequence (Tuple or List) of tuples of two indices, the first is the hit index, the second is the followup
alias of TypeVar(‘IndexMap’, bound=
Sequence[Tuple[int,int]])- __init__(name, *constraints, bound=None, covariant=False, contravariant=False)
- class fragmenstein.monster.ExtendedFMCSMode[source]
These are the acceptable types for the modes of FindMCS, plus three that can be configured in rdFMCS.MCSParameters
- __init__(*args, **kwargs)
- atomCompare: AtomCompare
- bondCompare: BondCompare
- clear() None. Remove all items from D.
- completeRingsOnly: bool
- copy() a shallow copy of D
- classmethod fromkeys(iterable, value=None, /)
Create a new dictionary with keys from iterable and values set to value.
- get(key, default=None, /)
Return the value for key if key is in the dictionary, else default.
- items() a set-like object providing a view on D's items
- keys() a set-like object providing a view on D's keys
- matchChiralTag: bool
- matchFormalCharge: bool
- matchStereo: bool
- matchValences: bool
- maxDistance: float
- maximizeBonds: bool
- pop(k[, d]) v, remove specified key and return the corresponding value.
If the key is not found, return the default if given; otherwise, raise a KeyError.
- popitem()
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order. Raises KeyError if the dict is empty.
- ringCompare: RingCompare
- ringMatchesRingOnly: bool
- seedSmarts: str
- setdefault(key, default=None, /)
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
- threshold: float
- timeout: int
- update([E, ]**F) None. Update D from dict/iterable E and F.
If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
- values() an object providing a view on D's values
- verbose: bool