public void TestGetBondLength() { PharmacophoreAtom patom1 = new PharmacophoreAtom("[CX2]N", "Amine", Vector3.Zero); PharmacophoreAtom patom2 = new PharmacophoreAtom("c1ccccc1", "Aromatic", new Vector3(1, 1, 1)); PharmacophoreBond pbond = new PharmacophoreBond(patom1, patom2); Assert.AreEqual(1.732051, pbond.BondLength, 0.00001); }
public void TestGetterSetter() { PharmacophoreAtom patom = new PharmacophoreAtom("[CX2]N", "Amine", Vector3.Zero); Assert.AreEqual("[CX2]N", patom.Smarts); patom.Smarts = "[OX2]"; Assert.AreEqual("[OX2]", patom.Smarts); }
public void TestGetAngle5() { PharmacophoreAtom patom1 = new PharmacophoreAtom("[CX2]N", "Amine", new Vector3(1, 1, 1)); PharmacophoreAtom patom2 = new PharmacophoreAtom("c1ccccc1", "Aromatic", Vector3.Zero); PharmacophoreAtom patom3 = new PharmacophoreAtom("C", "Blah", new Vector3(1, 0, 0)); PharmacophoreAngleBond pbond = new PharmacophoreAngleBond(patom1, patom2, patom3); Assert.AreEqual(54.7356, pbond.BondLength, 0.0001); }
private static PharmacophoreAtom NewPCoreAtom(IAtomContainer input, PharmacophoreQueryAtom qatom, string smarts, int[] mapping) { var coords = GetEffectiveCoordinates(input, mapping); var patom = new PharmacophoreAtom(smarts, qatom.Symbol, coords); // n.b. mapping[] copy is mad by pcore atom patom.SetMatchingAtoms(mapping); return(patom); }
public void TestMatchingAtoms() { PharmacophoreAtom patom = new PharmacophoreAtom("[CX2]N", "Amine", Vector3.Zero); patom.SetMatchingAtoms(new int[] { 1, 4, 5 }); int[] indices = patom.GetMatchingAtoms(); Assert.AreEqual(1, indices[0]); Assert.AreEqual(4, indices[1]); Assert.AreEqual(5, indices[2]); }
public override bool Equals(object o) { if (!(o is PharmacophoreAtom)) { return(false); } PharmacophoreAtom that = (PharmacophoreAtom)o; return(Smarts.Equals(that.Smarts, StringComparison.Ordinal) && Symbol.Equals(that.Symbol, StringComparison.Ordinal) && Point3D.Equals(that.Point3D) && Arrays.AreEqual(this.matchingAtoms, that.matchingAtoms)); }
/// <summary> /// Create a pharmacophore group. /// </summary> /// <param name="pharmacophoreAtom">A previously created pharmacophore group</param> public PharmacophoreAtom(PharmacophoreAtom pharmacophoreAtom) { Smarts = pharmacophoreAtom.Smarts; this.Symbol = pharmacophoreAtom.Symbol; Point3D = pharmacophoreAtom.Point3D; if (pharmacophoreAtom.GetMatchingAtoms() != null) { var indices = pharmacophoreAtom.GetMatchingAtoms(); matchingAtoms = new int[indices.Length]; Array.Copy(indices, 0, matchingAtoms, 0, indices.Length); } }
public void TestMatchedBonds() { Assert.IsNotNull(conformers); // make a query PharmacophoreQuery query = new PharmacophoreQuery(); PharmacophoreQueryAtom o = new PharmacophoreQueryAtom("D", "[OX1]"); PharmacophoreQueryAtom n1 = new PharmacophoreQueryAtom("A", "[N]"); PharmacophoreQueryAtom n2 = new PharmacophoreQueryAtom("A", "[N]"); query.Atoms.Add(o); query.Atoms.Add(n1); query.Atoms.Add(n2); PharmacophoreQueryBond b1 = new PharmacophoreQueryBond(o, n1, 4.0, 4.5); PharmacophoreQueryBond b2 = new PharmacophoreQueryBond(o, n2, 4.0, 5.0); PharmacophoreQueryBond b3 = new PharmacophoreQueryBond(n1, n2, 5.4, 5.8); query.Bonds.Add(b1); query.Bonds.Add(b2); query.Bonds.Add(b3); IAtomContainer conf1 = conformers[0]; PharmacophoreMatcher matcher = new PharmacophoreMatcher(query); bool status = matcher.Matches(conf1); Assert.IsTrue(status); var bMatches = matcher.GetMatchingPharmacophoreBonds(); Assert.AreEqual(2, bMatches.Count); // 2 since we haven't gotten a unique set Assert.AreEqual(3, bMatches[0].Count); PharmacophoreBond pbond = (PharmacophoreBond)BondRef.Deref(bMatches[0][0]); PharmacophoreAtom patom1 = (PharmacophoreAtom)AtomRef.Deref(pbond.Begin); PharmacophoreAtom patom2 = (PharmacophoreAtom)AtomRef.Deref(pbond.End); Assert.AreEqual("D", patom1.Symbol); Assert.AreEqual("A", patom2.Symbol); var bondMap = matcher.GetTargetQueryBondMappings(); Assert.AreEqual(2, bondMap.Count); var mapping = bondMap[0]; // get the 'BondRef' for lookup IBond value = mapping[bMatches[0][0]]; Assert.AreEqual(b1, value); }
/// <summary> /// Performs the pharmacophore matching. /// </summary> /// <param name="atomContainer">The target molecule. Must have 3D coordinates</param> /// <param name="initializeTarget">If <see langword="true"/>, the target molecule specified in the /// first argument will be analyzed to identify matching pharmacophore groups. If <see langword="false"/> /// this is not performed. The latter case is only useful when dealing with conformers /// since for a given molecule, all conformers will have the same pharmacophore groups /// and only the constraints will change from one conformer to another.</param> /// <returns><see langword="true"/> is the target molecule contains the query pharmacophore</returns> /// <exception cref="CDKException"> /// if the query pharmacophore was not set or the query is invalid or if the molecule /// does not have 3D coordinates</exception> public bool Matches(IAtomContainer atomContainer, bool initializeTarget) { if (!GeometryUtil.Has3DCoordinates(atomContainer)) { throw new CDKException("Molecule must have 3D coordinates"); } if (pharmacophoreQuery == null) { throw new CDKException("Must set the query pharmacophore before matching"); } if (!CheckQuery(pharmacophoreQuery)) { throw new CDKException("A problem in the query. Make sure all pharmacophore groups of the same symbol have the same same SMARTS"); } var title = atomContainer.Title; if (initializeTarget) { pharmacophoreMolecule = GetPharmacophoreMolecule(atomContainer); } else { // even though the atoms comprising the pcore groups are // constant, their coords will differ, so we need to make // sure we get the latest set of effective coordinates foreach (var iAtom in pharmacophoreMolecule.Atoms) { var patom = PharmacophoreAtom.Get(iAtom); var tmpList = new List <int>(); foreach (var idx in patom.GetMatchingAtoms()) { tmpList.Add(idx); } var coords = GetEffectiveCoordinates(atomContainer, tmpList); patom.Point3D = coords; } } if (pharmacophoreMolecule.Atoms.Count < pharmacophoreQuery.Atoms.Count) { Debug.WriteLine($"Target [{title}] did not match the query SMARTS. Skipping constraints"); return(false); } mappings = Pattern.FindSubstructure(pharmacophoreQuery).MatchAll(pharmacophoreMolecule); // XXX: doing one search then discarding return(mappings.AtLeast(1)); }
public void TestMatches() { PharmacophoreQueryAtom qatom = new PharmacophoreQueryAtom("aromatic", "c1ccccc1"); PharmacophoreAtom patom1 = new PharmacophoreAtom("c1ccccc1", "aromatic", Vector3.Zero); PharmacophoreAtom patom2 = new PharmacophoreAtom("c1ccccc1", "hydrophobic", Vector3.Zero); PharmacophoreAtom patom3 = new PharmacophoreAtom("Cc1ccccc1", "aromatic", Vector3.Zero); PharmacophoreAtom patom4 = new PharmacophoreAtom("[CX2]N", "amine", Vector3.Zero); Assert.IsTrue(qatom.Matches(patom1)); Assert.IsFalse(qatom.Matches(patom2)); Assert.IsTrue(qatom.Matches(patom3)); Assert.IsFalse(qatom.Matches(patom4)); }
public void TestMatches() { PharmacophoreAtom patom1 = new PharmacophoreAtom("[CX2]N", "Amine", Vector3.Zero); PharmacophoreAtom patom2 = new PharmacophoreAtom("c1ccccc1", "Aromatic", new Vector3(1, 1, 1)); PharmacophoreBond pbond = new PharmacophoreBond(patom1, patom2); PharmacophoreQueryAtom qatom1 = new PharmacophoreQueryAtom("Amine", "[CX2]N"); PharmacophoreQueryAtom qatom2 = new PharmacophoreQueryAtom("aromatic", "c1ccccc1"); PharmacophoreQueryBond qbond1 = new PharmacophoreQueryBond(qatom1, qatom2, 1.0, 2.0); PharmacophoreQueryBond qbond2 = new PharmacophoreQueryBond(qatom1, qatom2, 1.732); PharmacophoreQueryBond qbond3 = new PharmacophoreQueryBond(qatom1, qatom2, 0.1, 1.0); Assert.IsTrue(qbond1.Matches(pbond)); Assert.IsTrue(qbond2.Matches(pbond)); Assert.IsFalse(qbond3.Matches(pbond)); }
public void TestMatches() { PharmacophoreAtom patom1 = new PharmacophoreAtom("[CX2]N", "Amine", new Vector3(1, 1, 1)); PharmacophoreAtom patom2 = new PharmacophoreAtom("c1ccccc1", "Aromatic", Vector3.Zero); PharmacophoreAtom patom3 = new PharmacophoreAtom("C", "Blah", new Vector3(1, 0, 0)); PharmacophoreAngleBond pbond = new PharmacophoreAngleBond(patom1, patom2, patom3); PharmacophoreQueryAtom qatom1 = new PharmacophoreQueryAtom("Amine", "[CX2]N"); PharmacophoreQueryAtom qatom2 = new PharmacophoreQueryAtom("aromatic", "c1ccccc1"); PharmacophoreQueryAtom qatom3 = new PharmacophoreQueryAtom("blah", "C"); PharmacophoreQueryAngleBond qbond1 = new PharmacophoreQueryAngleBond(qatom1, qatom2, qatom3, 54.735); PharmacophoreQueryAngleBond qbond2 = new PharmacophoreQueryAngleBond(qatom1, qatom2, qatom3, 50, 60); PharmacophoreQueryAngleBond qbond3 = new PharmacophoreQueryAngleBond(qatom1, qatom2, qatom3, 60, 80); PharmacophoreQueryBond qbond4 = new PharmacophoreQueryBond(qatom1, qatom2, 1, 2); Assert.IsTrue(qbond1.Matches(pbond)); Assert.IsTrue(qbond2.Matches(pbond)); Assert.IsFalse(qbond3.Matches(pbond)); Assert.IsFalse(qbond4.Matches(pbond)); }
public void TestEquals() { PharmacophoreAtom patom1 = new PharmacophoreAtom("[CX2]N", "Amine", Vector3.Zero); patom1.SetMatchingAtoms(new int[] { 1, 4, 5 }); PharmacophoreAtom patom2 = new PharmacophoreAtom("[CX2]N", "Amine", Vector3.Zero); patom2.SetMatchingAtoms(new int[] { 1, 4, 5 }); PharmacophoreAtom patom3 = new PharmacophoreAtom("[CX2]N", "Amine", new Vector3(0, 1, 0)); patom3.SetMatchingAtoms(new int[] { 1, 4, 5 }); PharmacophoreAtom patom4 = new PharmacophoreAtom("[CX2]N", "Amine", Vector3.Zero); patom4.SetMatchingAtoms(new int[] { 1, 4, 6 }); Assert.AreEqual(patom2, patom1); Assert.AreNotSame(patom3, patom1); Assert.AreNotSame(patom4, patom1); }
/// <summary> /// Checks whether this query atom matches a target atom. /// <para> /// Currently a query pharmacophore atom will match a target pharmacophore group if the /// symbols of the two groups match. This is based on the assumption that /// pharmacophore groups with the same symbol will have the same SMARTS /// pattern. /// </para> /// </summary> /// <param name="atom">A target pharmacophore group</param> /// <returns>true if the current query group has the same symbol as the target group</returns> public bool Matches(IAtom atom) { var patom = PharmacophoreAtom.Get(atom); return(patom.Symbol.Equals(Symbol, StringComparison.Ordinal)); }
/// <summary> /// Create a pharmacophore distance constraint. /// </summary> /// <param name="patom1">The first pharmacophore group</param> /// <param name="patom2">The second pharmacophore group</param> /// <param name="patom3">The third pharmacophore group</param> public PharmacophoreAngleBond(PharmacophoreAtom patom1, PharmacophoreAtom patom2, PharmacophoreAtom patom3) : base(new PharmacophoreAtom[] { patom1, patom2, patom3 }) { }
/// <summary> /// Create a pharmacophore distance constraint. /// </summary> /// <param name="patom1">The first pharmacophore group</param> /// <param name="patom2">The second pharmacophore group</param> public PharmacophoreBond(PharmacophoreAtom patom1, PharmacophoreAtom patom2) : base(patom1, patom2) { }
/// <summary> /// Convert the input into a pcore molecule. /// </summary> /// <param name="input">the compound being converted from</param> /// <returns>pcore molecule </returns> /// <exception cref="CDKException">match failed</exception> private IAtomContainer GetPharmacophoreMolecule(IAtomContainer input) { // XXX: prepare query, to be moved PrepareInput(input); var pharmacophoreMolecule = input.Builder.NewAtomContainer(); var matched = new HashSet <string>(); var uniqueAtoms = new LinkedHashSet <PharmacophoreAtom>(); Debug.WriteLine($"Converting [{input.Title}] to a pcore molecule"); // lets loop over each pcore query atom foreach (var atom in pharmacophoreQuery.Atoms) { var qatom = (PharmacophoreQueryAtom)atom; var smarts = qatom.Smarts; // a pcore query might have multiple instances of a given pcore atom (say // 2 hydrophobic groups separated by X unit). In such a case we want to find // the atoms matching the pgroup SMARTS just once, rather than redoing the // matching for each instance of the pcore query atom. if (!matched.Add(qatom.Symbol)) { continue; } // see if the smarts for this pcore query atom gets any matches // in our query molecule. If so, then collect each set of // matching atoms and for each set make a new pcore atom and // add it to the pcore atom container object int count = 0; foreach (var query in qatom.CompiledSmarts) { // create the lazy mappings iterator var mappings = query.MatchAll(input).GetUniqueAtoms(); foreach (var mapping in mappings) { uniqueAtoms.Add(NewPCoreAtom(input, qatom, smarts, mapping)); count++; } } Debug.WriteLine($"\tFound {count} unique matches for {smarts}"); } pharmacophoreMolecule.SetAtoms(uniqueAtoms.ToArray()); // now that we have added all the pcore atoms to the container // we need to join all atoms with pcore bonds (i.e. distance constraints) if (HasDistanceConstraints(pharmacophoreQuery)) { var npatom = pharmacophoreMolecule.Atoms.Count; for (int i = 0; i < npatom - 1; i++) { for (int j = i + 1; j < npatom; j++) { var atom1 = PharmacophoreAtom.Get(pharmacophoreMolecule.Atoms[i]); var atom2 = PharmacophoreAtom.Get(pharmacophoreMolecule.Atoms[j]); var bond = new PharmacophoreBond(atom1, atom2); pharmacophoreMolecule.Bonds.Add(bond); } } } // if we have angle constraints, generate only the valid // possible angle relationships, rather than all possible if (HasAngleConstraints(pharmacophoreQuery)) { int nangleDefs = 0; foreach (var bond in pharmacophoreQuery.Bonds) { if (!(bond is PharmacophoreQueryAngleBond)) { continue; } var startQAtom = bond.Atoms[0]; var middleQAtom = bond.Atoms[1]; var endQAtom = bond.Atoms[2]; // make a list of the patoms in the target that match // each type of angle atom var startl = new List <IAtom>(); var middlel = new List <IAtom>(); var endl = new List <IAtom>(); foreach (var tatom in pharmacophoreMolecule.Atoms) { if (tatom.Symbol.Equals(startQAtom.Symbol, StringComparison.Ordinal)) { startl.Add(tatom); } if (tatom.Symbol.Equals(middleQAtom.Symbol, StringComparison.Ordinal)) { middlel.Add(tatom); } if (tatom.Symbol.Equals(endQAtom.Symbol, StringComparison.Ordinal)) { endl.Add(tatom); } } // now we form the relevant angles, but we will // have reversed repeats var tmpl = new List <IAtom[]>(); foreach (var middle in middlel) { foreach (var start in startl) { if (middle.Equals(start)) { continue; } foreach (var end in endl) { if (start.Equals(end) || middle.Equals(end)) { continue; } tmpl.Add(new IAtom[] { start, middle, end }); } } } // now clean up reversed repeats var unique = new List <IAtom[]>(); for (int i = 0; i < tmpl.Count; i++) { var seq1 = tmpl[i]; bool isRepeat = false; for (int j = 0; j < unique.Count; j++) { if (i == j) { continue; } var seq2 = unique[j]; if (Compares.AreDeepEqual(seq1[1], seq2[1]) && Compares.AreDeepEqual(seq1[0], seq2[2]) && Compares.AreDeepEqual(seq1[2], seq2[0])) { isRepeat = true; } } if (!isRepeat) { unique.Add(seq1); } } // finally we can add the unique angle to the target foreach (var seq in unique) { var pbond = new PharmacophoreAngleBond(PharmacophoreAtom.Get(seq[0]), PharmacophoreAtom.Get(seq[1]), PharmacophoreAtom.Get(seq[2])); pharmacophoreMolecule.Bonds.Add(pbond); nangleDefs++; } } Debug.WriteLine($"Added {nangleDefs} defs to the target pcore molecule"); } return(pharmacophoreMolecule); }