def calc_molfeatures(mol: Chem.Mol, features_generator: FeaturesGenerator): if mol is not None and mol.GetNumHeavyAtoms() > 0: molfeatures = features_generator(mol) # for H2 elif mol is not None and mol.GetNumHeavyAtoms() == 0: # not all molfeatures are equally long, so use methane as dummy # molecule to determine length molfeatures = np.zeros(len(features_generator( Chem.MolFromSmiles('C')))) else: molfeatures = None return np.asarray(molfeatures)
def CalculateFlexibility(mol: Chem.Mol) -> float: """Calculate Kier molecular flexibility index.""" kappa1 = CalculateKappaAlapha1(mol) kappa2 = CalculateKappaAlapha2(mol) A = mol.GetNumHeavyAtoms() phi = kappa1 * kappa2 / (A + 0.0) return round(phi, 3)
def CalculateKappa1(mol: Chem.Mol) -> float: """Calculate molecular shape index for one bonded fragment.""" P1 = mol.GetNumBonds(onlyHeavy=1) A = mol.GetNumHeavyAtoms() denom = P1 + 0.0 if denom: kappa = (A) * (A - 1)**2 / denom**2 else: kappa = 0.0 return round(kappa, 3)
def CalculateKappa2(mol: Chem.Mol) -> float: """Calculate molecular shape index for two bonded fragments.""" P2 = len(Chem.FindAllPathsOfLengthN(mol, 2)) A = mol.GetNumHeavyAtoms() denom = P2 + 0.0 if denom: kappa = (A - 1) * (A - 2)**2 / denom**2 else: kappa = 0.0 return round(kappa, 3)
def CalculateKappaAlapha1(mol: Chem.Mol) -> float: """Calculate molecular shape index for one bonded fragment.""" P1 = mol.GetNumBonds(onlyHeavy=1) A = mol.GetNumHeavyAtoms() alpha = _HallKierAlpha(mol) denom = P1 + alpha if denom: kappa = (A + alpha) * (A + alpha - 1)**2 / denom**2 else: kappa = 0.0 return round(kappa, 3)
def mmpa_cut(mol: Chem.Mol, rdkit_pattern: bool = False) -> Optional[Set[Any]]: """Cut molecules to perform mmpa analysis later Args: mol: Molecule to fragment. rdkit_pattern: Whether to perform the fragmentation using the default rdkit pattern: [#6+0;!$(*=, #[!#6])]!@!=!#[*]" Returns: List of 'smiles,core,chains' """ if mol is None: return mol outlines = set() smiles = dm.to_smiles(mol) if rdkit_pattern: frags = mmpa_frag(mol, max_cut=3, max_bond_cut=30) else: # heavy atoms frags = mmpa_frag(mol, pattern="[!#1]!@!=!#[!#1]", max_cut=4, max_bond_cut=30) frags.update( mmpa_frag(mol, pattern="[!#1]!@!=!#[!#1]", max_cut=3, max_bond_cut=30)) frags = set(frags) for core, chains in frags: output = f"{smiles},{core},{chains}\n" outlines.add(output) # hydrogen splitting mol = Chem.AddHs(mol) smiles = dm.to_smiles(mol) n = mol.GetNumHeavyAtoms() if n < 60: frags = mmpa_frag(mol, pattern=None, max_cut=1, max_bond_cut=100, h_split=True) for core, chains in frags: output = f"{smiles},{core},{chains}\n" outlines.add(output) return outlines
def CalculateKappa3(mol: Chem.Mol) -> float: """Calculate molecular shape index for three bonded fragments.""" P3 = len(Chem.FindAllPathsOfLengthN(mol, 3)) A = mol.GetNumHeavyAtoms() denom = P3 + 0.0 if denom: if A % 2 == 1: kappa = (A - 1) * (A - 3)**2 / denom**2 else: kappa = (A - 3) * (A - 2)**2 / denom**2 else: kappa = 0.0 return round(kappa, 3)
def CalculateHydrophilicityFactor(mol: Chem.Mol) -> float: """Calculate hydrophilicity factor. From Todeschini R. et al., SAR QSAR Environ Res (1997), 7,173-193. """ nheavy = mol.GetNumHeavyAtoms() nc = 0 for atom in mol.GetAtoms(): if atom.GetAtomicNum() == 6: nc += 1 nhy = 0 for atom in mol.GetAtoms(): if atom.GetAtomicNum() == 7 or atom.GetAtomicNum( ) == 8 or atom.GetAtomicNum() == 16: atomn = atom.GetNeighbors() for i in atomn: if i.GetAtomicNum() == 1: nhy += 1 res = ((1 + nhy) * math.log((1 + nhy), 2) + nc * (1.0 / nheavy * math.log(1.0 / nheavy, 2)) + math.sqrt( (nhy + 0.0) / (nheavy * nheavy))) / math.log(1.0 + nheavy) return round(res, 3)
def nr_hydrogens(mol: Mol): return mol.GetNumAtoms() - mol.GetNumHeavyAtoms()
def CalculateHeavyAtomNumber(mol: Chem.Mol) -> float: """Calculate number of Heavy atoms.""" return mol.GetNumHeavyAtoms()