/////////////////////////////////////////////////////////////////////////// // Query Methods // // This methods are simple applications of the RGraph model on atom containers // using different constrains and search options. They give an exemple of the // most common queries but of course it is possible to define other type of // queries exploiting the constrain and option combinations // //// // Isomorphism search /// <summary> Tests if g1 and g2 are isomorph /// /// </summary> /// <param name="g1"> first molecule /// </param> /// <param name="g2"> second molecule /// </param> /// <returns> true if the 2 molecule are isomorph /// </returns> public static bool isIsomorph(IAtomContainer g1, IAtomContainer g2) { if (g2.AtomCount != g1.AtomCount) { return(false); } // check single atom case if (g2.AtomCount == 1) { IAtom atom = g1.getAtomAt(0); IAtom atom2 = g2.getAtomAt(0); if (atom is IQueryAtom) { IQueryAtom qAtom = (IQueryAtom)atom; return(qAtom.matches(g2.getAtomAt(0))); } else if (atom2 is IQueryAtom) { IQueryAtom qAtom = (IQueryAtom)atom2; return(qAtom.matches(g1.getAtomAt(0))); } else { System.String atomSymbol = atom.Symbol; return(g1.getAtomAt(0).Symbol.Equals(atomSymbol)); } } return(getIsomorphMap(g1, g2) != null); }
/// <summary> Checks for single atom cases before doing subgraph/isomorphism search /// /// </summary> /// <param name="g1"> AtomContainer to match on /// </param> /// <param name="g2"> AtomContainer as query /// </param> /// <returns> List of List of RMap objects for the Atoms (not Bonds!), null if no single atom case /// </returns> public static System.Collections.ArrayList checkSingleAtomCases(IAtomContainer g1, IAtomContainer g2) { if (g2.AtomCount == 1) { System.Collections.ArrayList arrayList = new System.Collections.ArrayList(); IAtom atom = g2.getAtomAt(0); if (atom is IQueryAtom) { IQueryAtom qAtom = (IQueryAtom)atom; for (int i = 0; i < g1.AtomCount; i++) { if (qAtom.matches(g1.getAtomAt(i))) { arrayList.Add(new RMap(i, 0)); } } } else { System.String atomSymbol = atom.Symbol; for (int i = 0; i < g1.AtomCount; i++) { if (g1.getAtomAt(i).Symbol.Equals(atomSymbol)) { arrayList.Add(new RMap(i, 0)); } } } return(arrayList); } else if (g1.AtomCount == 1) { System.Collections.ArrayList arrayList = new System.Collections.ArrayList(); IAtom atom = g1.getAtomAt(0); for (int i = 0; i < g2.AtomCount; i++) { IAtom atom2 = g2.getAtomAt(i); if (atom2 is IQueryAtom) { IQueryAtom qAtom = (IQueryAtom)atom2; if (qAtom.matches(atom)) { arrayList.Add(new RMap(0, i)); } } else { if (atom2.Symbol.Equals(atom.Symbol)) { arrayList.Add(new RMap(0, i)); } } } return(arrayList); } else { return(null); } }
public object Visit(ASTExplicitAtom node, object data) { IQueryAtom atom = null; var symbol = node.Symbol; switch (symbol) { case "*": atom = new AnyAtom(builder); break; case "A": atom = new AliphaticAtom(builder); break; case "a": atom = new AromaticAtom(builder); break; case "o": case "n": case "c": case "s": case "p": case "as": case "se": var atomSymbol = symbol.Substring(0, 1).ToUpperInvariant() + symbol.Substring(1); atom = new AromaticSymbolAtom(atomSymbol, builder); break; case "H": atom = new HydrogenAtom(builder) { Symbol = symbol.ToUpperInvariant(), MassNumber = 1 }; break; case "D": atom = new HydrogenAtom(builder) { Symbol = symbol.ToUpperInvariant(), MassNumber = 2 }; break; case "T": atom = new HydrogenAtom(builder) { Symbol = symbol.ToUpperInvariant(), MassNumber = 3 }; break; default: atom = new AliphaticSymbolAtom(symbol, builder); break; } return(atom); }
/// <summary> /// Create a negation of <paramref name="expression"/>. /// </summary> /// <param name="expression">the expression to negate</param> public Negation(IQueryAtom expression) : base() { this.expression = (SMARTSAtom)expression; this.chiral = expression.GetType().Equals(typeof(ChiralityAtom)); base.Left = expression; base.Operator = "not"; }
/// <summary> /// Create a disjunction of <see cref="Left"/> or <see cref="right"/>. /// </summary> /// <param name="builder">chem object builder</param> /// <param name="left">the expression to negate</param> /// <param name="right">the expression to negate</param> public Disjunction(IChemObjectBuilder builder, IQueryAtom left, IQueryAtom right) : base(builder) { this.left = (SMARTSAtom)left; this.right = (SMARTSAtom)right; base.Left = left; base.Right = right; base.Operator = "or"; }
/// <summary> /// Create a disjunction of <see cref="Left"/> or <see cref="right"/>. /// </summary> /// <param name="left">the expression to negate</param> /// <param name="right">the expression to negate</param> public Disjunction(IQueryAtom left, IQueryAtom right) : base() { this.left = (SMARTSAtom)left; this.right = (SMARTSAtom)right; base.Left = left; base.Right = right; base.Operator = "or"; }
public object Visit(ASTAtom node, object data) { IQueryAtom atom = (IQueryAtom)node.JjtGetChild(0).JjtAccept(this, data); for (int i = 1; i < node.JjtGetNumChildren(); i++) { // if there are ring identifiers throw new InvalidOperationException(); } return(atom); }
public void TestUnspecifiedIsotope() { IAtom aexpr = Smiles.SMARTS.Parser.SMARTSParser.Parse("[!0]", CDK.Builder).Atoms[0]; Assert.IsInstanceOfType(aexpr, typeof(LogicalOperatorAtom)); Assert.AreEqual("not", ((LogicalOperatorAtom)aexpr).Operator); IQueryAtom subexpr = ((LogicalOperatorAtom)aexpr).Left; Assert.IsInstanceOfType(subexpr, typeof(MassAtom)); Assert.AreEqual(0, subexpr.MassNumber); }
public object Visit(ASTReaction node, object data) { IAtomContainer query = new QueryAtomContainer(builder); for (int grpIdx = 0; grpIdx < node.JjtGetNumChildren(); grpIdx++) { int rollback = query.Atoms.Count; ASTGroup group = (ASTGroup)node.JjtGetChild(grpIdx); group.JjtAccept(this, query); // fill in the roles for newly create atoms if (group.Role != ReactionRoles.Any) { IQueryAtom roleQueryAtom = null; ReactionRole?role = null; // use single instances switch (group.Role) { case ReactionRoles.Reactant: roleQueryAtom = ReactionRoleQueryAtom.RoleReactant; role = ReactionRole.Reactant; break; case ReactionRoles.Agent: roleQueryAtom = ReactionRoleQueryAtom.RoleAgent; role = ReactionRole.Agent; break; case ReactionRoles.Product: roleQueryAtom = ReactionRoleQueryAtom.RoleProduct; role = ReactionRole.Product; break; } if (roleQueryAtom != null) { while (rollback < query.Atoms.Count) { IAtom org = query.Atoms[rollback]; IAtom rep = LogicalOperatorAtom.And(roleQueryAtom, (IQueryAtom)org); // ensure AAM is propagated rep.SetProperty(CDKPropertyName.AtomAtomMapping, org.GetProperty <int?>(CDKPropertyName.AtomAtomMapping)); rep.SetProperty(CDKPropertyName.ReactionRole, role); AtomContainerManipulator.ReplaceAtomByAtom(query, org, rep); rollback++; } } } } return(query); }
/// <summary> /// Store the specified bond index and mapped query atom (optional) /// on the stack. /// </summary> /// <param name="bidx">bond index</param> /// <param name="queryatom">query atom - can be null</param> private void Store(int bidx, IQueryAtom queryatom) { ++sptr; stack[sptr].bidx = bidx; stack[sptr].iter = null; if (queryatom != null) { stack[sptr].atom = queryatom; } else { stack[sptr].atom = null; } }
/// <summary> /// Determine if a atom from the molecule is unvisited and if it is matched /// by the query atom. If the match is feasible the provided query bond index /// stored on the stack. /// </summary> /// <param name="bidx">atom from the query</param> /// <param name="atom">atom from the molecule</param> /// <returns>the match was feasible and the state was stored</returns> private bool Feasible(int bidx, IQueryAtom qatom, IAtom atom) { var aidx = atom.Index; if (avisit[aidx] || !qatom.Matches(atom)) { return(false); } ++numMapped; amap[qatom.Index] = aidx; avisit[aidx] = true; Store(bidx, qatom); return(true); }
/// <summary> Tests if g2 a subgraph of g1 /// /// </summary> /// <param name="g1"> first molecule /// </param> /// <param name="g2"> second molecule /// </param> /// <returns> true if g2 a subgraph on g1 /// </returns> public static bool isSubgraph(IAtomContainer g1, IAtomContainer g2) { if (g2.AtomCount > g1.AtomCount) { return(false); } // test for single atom case if (g2.AtomCount == 1) { IAtom atom = g2.getAtomAt(0); for (int i = 0; i < g1.AtomCount; i++) { IAtom atom2 = g1.getAtomAt(i); if (atom is IQueryAtom) { IQueryAtom qAtom = (IQueryAtom)atom; if (qAtom.matches(atom2)) { return(true); } } else if (atom2 is IQueryAtom) { IQueryAtom qAtom = (IQueryAtom)atom2; if (qAtom.matches(atom)) { return(true); } } else { if (atom2.Symbol.Equals(atom.Symbol)) { return(true); } } } return(false); } if (!testSubgraphHeuristics(g1, g2)) { return(false); } return(getSubgraphMap(g1, g2) != null); }
/// <summary> Builds the nodes of the RGraph ( resolution graph ), from /// two atom containers (description of the two molecules to compare) /// /// </summary> /// <param name="gr"> the target RGraph /// </param> /// <param name="ac1"> description of the first molecule /// </param> /// <param name="ac2"> description of the second molecule /// </param> private static void nodeConstructor(RGraph gr, IAtomContainer ac1, IAtomContainer ac2) { // resets the target graph. gr.clear(); IBond[] bondsA1 = ac1.Bonds; IBond[] bondsA2 = ac2.Bonds; // compares each bond of G1 to each bond of G2 for (int i = 0; i < bondsA1.Length; i++) { for (int j = 0; j < bondsA2.Length; j++) { if (timeout > -1 && ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 - start) > timeout) { throw new CDKException("Timeout exceeded in getOverlaps"); } IBond bondA2 = bondsA2[j]; if (bondA2 is IQueryBond) { IQueryBond queryBond = (IQueryBond)bondA2; IQueryAtom atom1 = (IQueryAtom)(bondA2.getAtomAt(0)); IQueryAtom atom2 = (IQueryAtom)(bondA2.getAtomAt(1)); IBond bond = bondsA1[i]; if (queryBond.matches(bond)) { // ok, bonds match if (atom1.matches(bond.getAtomAt(0)) && atom2.matches(bond.getAtomAt(1)) || atom1.matches(bond.getAtomAt(1)) && atom2.matches(bond.getAtomAt(0))) { // ok, atoms match in either order gr.addNode(new RNode(i, j)); } } } else { // if both bonds are compatible then create an association node // in the resolution graph if (((bondsA1[i].Order == bondsA2[j].Order && bondsA1[i].getFlag(CDKConstants.ISAROMATIC) == bondsA2[j].getFlag(CDKConstants.ISAROMATIC)) || (bondsA1[i].getFlag(CDKConstants.ISAROMATIC) && bondsA2[j].getFlag(CDKConstants.ISAROMATIC))) && ((bondsA1[i].getAtomAt(0).Symbol.Equals(bondsA2[j].getAtomAt(0).Symbol) && bondsA1[i].getAtomAt(1).Symbol.Equals(bondsA2[j].getAtomAt(1).Symbol)) || (bondsA1[i].getAtomAt(0).Symbol.Equals(bondsA2[j].getAtomAt(1).Symbol) && bondsA1[i].getAtomAt(1).Symbol.Equals(bondsA2[j].getAtomAt(0).Symbol)))) { gr.addNode(new RNode(i, j)); } } } } }
public object Visit(ASTRingIdentifier node, object data) { IQueryAtom atom = (IQueryAtom)data; RingIdentifierAtom ringIdAtom = new RingIdentifierAtom(builder) { Atom = atom }; IQueryBond bond; if (node.JjtGetNumChildren() == 0) { // implicit bond bond = null; } else { bond = (IQueryBond)node.JjtGetChild(0).JjtAccept(this, data); } ringIdAtom.RingBond = bond; return(ringIdAtom); }
private static IQuery Build(IQueryAtomContainer queryMolecule) { VFQueryBuilder result = new VFQueryBuilder(); foreach (var atoms in queryMolecule.Atoms) { IQueryAtom atom = (IQueryAtom)atoms; IVFAtomMatcher matcher = CreateAtomMatcher(atom, queryMolecule); if (matcher != null) { result.AddNode(matcher, atom); } } for (int i = 0; i < queryMolecule.Bonds.Count; i++) { IBond bond = queryMolecule.Bonds[i]; IQueryAtom atomI = (IQueryAtom)bond.Begin; IQueryAtom atomJ = (IQueryAtom)bond.End; result.Connect(result.GetNode(atomI), result.GetNode(atomJ), CreateBondMatcher((IQueryBond)bond)); } return(result); }
internal static bool IsMatchFeasible(IAtomContainer ac1, IBond bondA1, IAtomContainer ac2, IBond bondA2, bool shouldMatchBonds) { if (ac1 is IQueryAtomContainer) { if (((IQueryBond)bondA1).Matches(bondA2)) { IQueryAtom atom1 = (IQueryAtom)(bondA1.Begin); IQueryAtom atom2 = (IQueryAtom)(bondA1.End); // ok, bonds match if (atom1.Matches(bondA2.Begin) && atom2.Matches(bondA2.End) || atom1.Matches(bondA2.End) && atom2.Matches(bondA2.Begin)) { // ok, atoms match in either order return(true); } return(false); } return(false); } else { //Bond Matcher var bondMatcher = new Matchers.DefaultBondMatcher(ac1, bondA1, shouldMatchBonds); //Atom Matcher var atomMatcher1 = new Matchers.DefaultMCSPlusAtomMatcher(ac1, bondA1.Begin, shouldMatchBonds); //Atom Matcher var atomMatcher2 = new Matchers.DefaultMCSPlusAtomMatcher(ac1, bondA1.End, shouldMatchBonds); if (Matchers.DefaultMatcher.IsBondMatch(bondMatcher, ac2, bondA2, shouldMatchBonds) && Matchers.DefaultMatcher.IsAtomMatch(atomMatcher1, atomMatcher2, ac2, bondA2, shouldMatchBonds)) { return(true); } return(false); } }
public AromaticQueryBond(IQueryAtom atom1, IQueryAtom atom2, BondOrder order) : base(atom1, atom2, order) { IsAromatic = true; }
/// <summary> /// Creates a new instance /// </summary> public AromaticOrSingleQueryBond(IQueryAtom atom1, IQueryAtom atom2, BondOrder order, IChemObjectBuilder builder) : base(atom1, atom2, order, builder) { IsAromatic = true; }
/// <summary> /// Creates a new instance. /// </summary> /// <param name="atom1"></param> /// <param name="atom2"></param> /// <param name="order"></param> public AnyOrderQueryBond(IQueryAtom atom1, IQueryAtom atom2, BondOrder order) : base(atom1, atom2, order) { }
/// <summary> /// Conjunction the provided expressions. /// </summary> /// <param name="left">expression</param> /// <param name="right">expression</param> /// <returns>conjunction of the left and right expressions</returns> public static SMARTSAtom And(IQueryAtom left, IQueryAtom right) { return(new Conjunction(left, right)); }
private static IVFAtomMatcher CreateAtomMatcher(IQueryAtom atom, IQueryAtomContainer container) { return(new DefaultVFAtomMatcher(atom, container)); }
/// <summary> /// Disjunction the provided expressions. /// </summary> /// <param name="left">expression</param> /// <param name="right">expression</param> /// <returns>disjunction of the left and right expressions</returns> public static SMARTSAtom Or(IQueryAtom left, IQueryAtom right) { return(new Disjunction(left, right)); }
public OrderQueryBond(IQueryAtom atom1, IQueryAtom atom2, BondOrder order, IChemObjectBuilder builder) : base(atom1, atom2, order, builder) { }
private static double GetBondTypeMatches(IBond queryBond, IBond targetBond) { double score = 0; if (targetBond is IQueryBond && queryBond is IBond) { IQueryBond bond = (IQueryBond)targetBond; IQueryAtom atom1 = (IQueryAtom)(targetBond.Atoms[0]); IQueryAtom atom2 = (IQueryAtom)(targetBond.Atoms[1]); if (bond.Matches(queryBond)) { // ok, bonds match if (atom1.Matches(queryBond.Atoms[0]) && atom2.Matches(queryBond.Atoms[1]) || atom1.Matches(queryBond.Atoms[1]) && atom2.Matches(queryBond.Atoms[0])) { // ok, atoms match in either order score += 4; } } else { score -= 4; } } else if (queryBond is IQueryBond && targetBond is IBond) { IQueryBond bond = (IQueryBond)queryBond; IQueryAtom atom1 = (IQueryAtom)(queryBond.Atoms[0]); IQueryAtom atom2 = (IQueryAtom)(queryBond.Atoms[1]); if (bond.Matches(targetBond)) { // ok, bonds match if (atom1.Matches(targetBond.Atoms[0]) && atom2.Matches(targetBond.Atoms[1]) || atom1.Matches(targetBond.Atoms[1]) && atom2.Matches(targetBond.Atoms[0])) { // ok, atoms match in either order score += 4; } } else { score -= 4; } } else { int reactantBondType = ConvertBondOrder(queryBond); int productBondType = ConvertBondOrder(targetBond); int rStereo = ConvertBondStereo(queryBond); int pStereo = ConvertBondStereo(targetBond); if ((queryBond.IsAromatic == targetBond.IsAromatic) && (reactantBondType == productBondType)) { score += 8; } else if (queryBond.IsAromatic && targetBond.IsAromatic) { score += 4; } if (reactantBondType == productBondType) { score += productBondType; } else { score -= 4 * Math.Abs(reactantBondType - productBondType); } if (rStereo != 4 || pStereo != 4 || rStereo != 3 || pStereo != 3) { if (rStereo == pStereo) { score += 1; } else { score -= 1; } } } return(score); }
private void HandleRingClosure(IQueryAtom atom, ASTRingIdentifier ringIdentifier) { RingIdentifierAtom ringIdAtom = (RingIdentifierAtom)ringIdentifier.JjtAccept(this, atom); // if there is already a RingIdentifierAtom, create a bond between // them and add the bond to the query int ringId = ringIdentifier.RingId; // ring digit > 9 - expand capacity if (ringId >= ringAtoms.Length) { ringAtoms = Arrays.CopyOf(ringAtoms, 100); } // Ring Open if (ringAtoms[ringId] == null) { ringAtoms[ringId] = ringIdAtom; if (neighbors.ContainsKey(atom)) { neighbors[atom].Add(ringIdAtom); } } // Ring Close else { IQueryBond ringBond; // first check if the two bonds ma if (ringAtoms[ringId].RingBond == null) { if (ringIdAtom.RingBond == null) { if (atom is AromaticSymbolAtom && ringAtoms[ringId].Atom is AromaticSymbolAtom) { ringBond = new AromaticQueryBond(builder); } else { ringBond = new RingBond(builder); } } else { ringBond = ringIdAtom.RingBond; } } else { // Here I assume the bond are always same. This should be checked by the parser already ringBond = ringAtoms[ringId].RingBond; } ((IBond)ringBond).SetAtoms(new[] { ringAtoms[ringId].Atom, atom }); query.Bonds.Add((IBond)ringBond); // if the connected atoms was tracking neighbors, replace the // placeholder reference if (neighbors.ContainsKey(ringAtoms[ringId].Atom)) { IList <IAtom> localNeighbors = neighbors[ringAtoms[ringId].Atom]; localNeighbors[localNeighbors.IndexOf(ringAtoms[ringId])] = atom; } if (neighbors.ContainsKey(atom)) { neighbors[atom].Add(ringAtoms[ringId].Atom); } ringAtoms[ringId] = null; } }
public SMARTSBond(IQueryAtom atom1, IQueryAtom atom2, BondOrder order) : base(atom1, atom2, order) { }
/// <summary> /// Constructor /// </summary> /// <param name="smartQueryAtom">query atom</param> /// <param name="container"></param> public DefaultVFAtomMatcher(IQueryAtom smartQueryAtom, IQueryAtomContainer container) : base() { this.smartQueryAtom = smartQueryAtom; this.symbol = smartQueryAtom.Symbol; }
/// <summary> /// Constructor /// </summary> /// <param name="smartQueryAtom">query atom</param> /// <param name="container"></param> public DefaultMCSPlusAtomMatcher(IQueryAtom smartQueryAtom, IQueryAtomContainer container) : this() { this.smartQueryAtom = smartQueryAtom; this.symbol = smartQueryAtom.Symbol; }
public OrderQueryBondOrderOnly(IQueryAtom atom1, IQueryAtom atom2, BondOrder order) : base(atom1, atom2, order) { }
/// <summary> /// Negate the provided expression. /// </summary> /// <param name="expr">expression to negate</param> /// <returns>a SMARTS atom which is the negation of the expression</returns> public static SMARTSAtom Not(IQueryAtom expr) { return(new Negation(expr)); }