Example #1
0
        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]));
        }
Example #2
0
        /// <summary>
        /// Set the recursive value of this atom expression.
        /// </summary>
        /// <param name="type">the type of expression</param>
        /// <param name="mol">the recursive pattern</param>
        private void SetRecursive(ExprType type, IAtomContainer mol)
        {
            switch (type)
            {
            case ExprType.Recursive:
                this.type  = type;
                this.value = 0;
                this.left  = null;
                this.right = null;
                this.query = mol;
                this.ptrn  = null;
                break;

            default:
                throw new ArgumentException();
            }
        }
Example #3
0
        /// <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));
            }
        }
Example #4
0
 public override Pattern Create(IAtomContainer container)
 {
     return(DfPattern.CreateSubstructureFinder(container));
 }