public void MatchRoot() { var mol = Smi("OC(=O)C(=O)O"); var qry = Sma("O=*"); var ptrn = DfPattern.CreateSubstructureFinder(qry); Assert.IsFalse(ptrn.MatchesRoot(mol.Atoms[0])); Assert.IsTrue(ptrn.MatchesRoot(mol.Atoms[2])); Assert.IsTrue(ptrn.MatchesRoot(mol.Atoms[4])); Assert.IsFalse(ptrn.MatchesRoot(mol.Atoms[5])); }
/// <summary> /// Internal match methods - does not null check. /// </summary> /// <param name="type">the type</param> /// <param name="atom">the atom</param> /// <returns>the expression matches</returns> private bool Matches(ExprType type, IAtom atom, int stereo) { switch (type) { // predicates case ExprType.True: return(true); case ExprType.False: return(false); case ExprType.IsAromatic: return(atom.IsAromatic); case ExprType.IsAliphatic: return(!atom.IsAromatic); case ExprType.IsInRing: return(atom.IsInRing); case ExprType.IsInChain: return(!atom.IsInRing); case ExprType.IsHetero: return(!Eq(atom.AtomicNumber, 6) && !Eq(atom.AtomicNumber, 1)); case ExprType.HasImplicitHydrogen: return(atom.ImplicitHydrogenCount != null && atom.ImplicitHydrogenCount > 0); case ExprType.HasIsotope: return(atom.MassNumber != null); case ExprType.HasUnspecifiedIsotope: return(atom.MassNumber == null); case ExprType.Unsaturated: foreach (var bond in atom.Bonds) { if (bond.Order == BondOrder.Double) { return(true); } } return(false); // value primitives case ExprType.Element: return(Eq(atom.AtomicNumber, value)); case ExprType.AliphaticElement: return(!atom.IsAromatic && Eq(atom.AtomicNumber, value)); case ExprType.AromaticElement: return(atom.IsAromatic && Eq(atom.AtomicNumber, value)); case ExprType.ImplicitHCount: return(Eq(atom.ImplicitHydrogenCount, value)); case ExprType.TotalHCount: if (atom.ImplicitHydrogenCount != null && atom.ImplicitHydrogenCount > value) { return(false); } return(GetTotalHCount(atom) == value); case ExprType.Degree: return(atom.Bonds.Count == value); case ExprType.HeavyDegree: // XXX: CDK quirk return(atom.Bonds.Count - (GetTotalHCount(atom) - atom.ImplicitHydrogenCount) == value); case ExprType.TotalDegree: int x = atom.Bonds.Count + Unbox(atom.ImplicitHydrogenCount); return(x == value); case ExprType.Valence: int v = Unbox(atom.ImplicitHydrogenCount); if (v > value) { return(false); } foreach (var bond in atom.Bonds) { if (!bond.Order.IsUnset()) { v += bond.Order.Numeric(); } } return(v == value); case ExprType.Isotope: return(Eq(atom.MassNumber, value)); case ExprType.FormalCharge: return(Eq(atom.FormalCharge, value)); case ExprType.RingBondCount: if (!atom.IsInRing || atom.Bonds.Count < value) { return(false); } int rbonds = 0; foreach (var bond in atom.Bonds) { rbonds += bond.IsInRing ? 1 : 0; } return(rbonds == value); case ExprType.RingCount: return(atom.IsInRing && GetRingCount(atom) == value); case ExprType.RingSmallest: return(atom.IsInRing && IsInSmallRingSize(atom, value)); case ExprType.RingSize: return(atom.IsInRing && IsInRingSize(atom, value)); case ExprType.HeteroSubstituentCount: if (atom.Bonds.Count < value) { return(false); } int q = 0; foreach (var bond in atom.Bonds) { q += Matches(ExprType.IsHetero, bond.GetOther(atom), stereo) ? 1 : 0; } return(q == value); case ExprType.Insaturation: int db = 0; foreach (var bond in atom.Bonds) { if (bond.Order == BondOrder.Double) { db++; } } return(db == value); case ExprType.HybridisationNumber: var hyb = atom.Hybridization; if (hyb.IsUnset()) { return(false); } switch (value) { case 1: return(hyb == Hybridization.SP1); case 2: return(hyb == Hybridization.SP2); case 3: return(hyb == Hybridization.SP3); case 4: return(hyb == Hybridization.SP3D1); case 5: return(hyb == Hybridization.SP3D2); case 6: return(hyb == Hybridization.SP3D3); case 7: return(hyb == Hybridization.SP3D4); case 8: return(hyb == Hybridization.SP3D5); default: return(false); } case ExprType.PeriodicGroup: return(Tools.PeriodicTable.GetGroup(atom.AtomicNumber) == value); case ExprType.Stereochemistry: return(stereo == UnknownStereo || stereo == value); case ExprType.ReactionRole: var role = atom.GetProperty <ReactionRole>(CDKPropertyName.ReactionRole); return(!role.IsUnset() && role.Ordinal() == value); case ExprType.And: return(left.Matches(left.type, atom, stereo) && right.Matches(right.type, atom, stereo)); case ExprType.Or: return(left.Matches(left.type, atom, stereo) || right.Matches(right.type, atom, stereo)); case ExprType.Not: return(!left.Matches(left.type, atom, stereo) // XXX: ugly but needed, when matching stereo || (stereo == UnknownStereo && (left.type == ExprType.Stereochemistry || left.type == ExprType.Or && left.left.type == ExprType.Stereochemistry))); case ExprType.Recursive: if (ptrn == null) { ptrn = DfPattern.CreateSubstructureFinder(query); } return(ptrn.MatchesRoot(atom)); default: throw new ArgumentException($"Cannot match AtomExpr, type={type}", nameof(type)); } }
public override Pattern Create(IAtomContainer container) { return(DfPattern.CreateSubstructureFinder(container)); }