public void CopySgroups2() { var sgroups = new List <Sgroup>(); var replace = new CDKObjectMap(); IAtom a1 = new Mock <IAtom>().Object; IAtom a2 = new Mock <IAtom>().Object; IBond b1 = new Mock <IBond>().Object; IBond b2 = new Mock <IBond>().Object; IAtom a1copy = new Mock <IAtom>().Object; IAtom a2copy = new Mock <IAtom>().Object; IBond b1copy = new Mock <IBond>().Object; IBond b2copy = new Mock <IBond>().Object; replace.Add(a1, a1copy); replace.Add(a2, a2copy); replace.Add(b1, b1copy); replace.Add(b2, b2copy); Sgroup sgroup = new Sgroup { Type = SgroupType.CtabStructureRepeatUnit, Subscript = "n" }; sgroup.Atoms.Add(a1); sgroup.Atoms.Add(a2); sgroup.Bonds.Add(b1); sgroup.Bonds.Add(b2); sgroups.Add(sgroup); var copied = SgroupManipulator.Copy(sgroups, replace); Sgroup copiedSgroup = copied[0]; Assert.AreNotSame(sgroup, copiedSgroup); Assert.AreEqual(sgroup.Type, copiedSgroup.Type); Assert.AreEqual(sgroup.Subscript, copiedSgroup.Subscript); Assert.IsFalse(Compares.AreDeepEqual(sgroup.Atoms, copiedSgroup.Atoms)); Assert.IsFalse(Compares.AreDeepEqual(sgroup.Bonds, copiedSgroup.Bonds)); Assert.IsTrue(copiedSgroup.Atoms.Contains(a1copy)); Assert.IsTrue(copiedSgroup.Atoms.Contains(a2copy)); Assert.IsTrue(copiedSgroup.Bonds.Contains(b1copy)); Assert.IsTrue(copiedSgroup.Bonds.Contains(b2copy)); }
public override ICDKObject Clone(CDKObjectMap map) { if (map == null) { throw new ArgumentNullException(nameof(map)); } if (map.TryGetValue(this, out IAtom clone)) { return(clone); } clone = (Atom)base.Clone(map); map.Add(this, clone); return(clone); }
public override ICDKObject Clone(CDKObjectMap map) { if (map == null) { throw new ArgumentNullException(nameof(map)); } if (map.TryGetValue(this, out IBond iclone)) { return(iclone); } var clone = (Bond)base.Clone(map); // clone all the Atoms if (atoms != null) { clone.InitAtoms(atoms.Select(n => (IAtom)n?.Clone(map))); } map.Add(this, clone); return(clone); }
/// <summary> /// Create a query from a molecule and a provided set of expressions. The /// molecule is converted and any features specified in the <paramref name="opts"/> /// will be matched. /// </summary> /// <remarks> /// A good starting point is the following options: /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Isomorphisms.Matchers.QueryAtomContainer_Example.cs+Create1"]/*' /> /// Specifying <see cref="ExprType.Degree"/> (or <see cref="ExprType.TotalDegree"/> + /// <see cref="ExprType.ImplicitHCount"/>) means the molecule will not match as a /// substructure. /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Isomorphisms.Matchers.QueryAtomContainer_Example.cs+Create2"]/*' /> /// The <see cref="ExprType.RingBondCount"/> property is useful for locking in /// ring systems. Specifying the ring bond count on benzene means it will /// not match larger ring systems (e.g. naphthalenee) but can still be /// substituted. /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Isomorphisms.Matchers.QueryAtomContainer_Example.cs+Create3"]/*' /> /// Note that <see cref="ExprType.FormalCharge"/>, /// <see cref="ExprType.ImplicitHCount"/>, and <see cref="ExprType.Isotope"/> are ignored /// if <see langword="null"/>. Explicitly setting these to zero (only required for Isotope from /// SMILES) forces their inclusion. /// <include file='IncludeExamples.xml' path='Comments/Codes[@id="NCDK.Isomorphisms.Matchers.QueryAtomContainer_Example.cs+Create4"]/*' /> /// Please note not all <see cref="ExprType"/>s are currently supported, if you /// require a specific type that you think is useful please open an issue. /// </remarks> /// <param name="mol">the molecule</param> /// <param name="opts">set of the expr types to match</param> /// <returns>the query molecule</returns> public static QueryAtomContainer Create(IAtomContainer mol, params ExprType[] opts) { var optset = new HashSet <ExprType>(opts); var query = new QueryAtomContainer(); var mapping = new CDKObjectMap(); var stereos = new Dictionary <IChemObject, IStereoElement <IChemObject, IChemObject> >(); foreach (var se in mol.StereoElements) { stereos[se.Focus] = se; } var qstereo = new List <IStereoElement <IChemObject, IChemObject> >(); foreach (var atom in mol.Atoms) { var expr = new Expr(); // isotope first if (optset.Contains(ExprType.Isotope) && atom.MassNumber != null) { expr.And(new Expr(ExprType.Isotope, atom.MassNumber.Value)); } if (atom.AtomicNumber != 0) { if (atom.IsAromatic) { if (optset.Contains(ExprType.AromaticElement)) { expr.And(new Expr(ExprType.AromaticElement, atom.AtomicNumber)); } else { if (optset.Contains(ExprType.IsAromatic)) { if (optset.Contains(ExprType.Element)) { expr.And(new Expr(ExprType.AromaticElement, atom.AtomicNumber)); } else { expr.And(new Expr(ExprType.IsAromatic)); } } else if (optset.Contains(ExprType.Element)) { expr.And(new Expr(ExprType.Element, atom.AtomicNumber)); } } } else { if (optset.Contains(ExprType.AliphaticElement)) { expr.And(new Expr(ExprType.AliphaticElement, atom.AtomicNumber)); } else { if (optset.Contains(ExprType.IsAliphatic)) { if (optset.Contains(ExprType.Element)) { expr.And(new Expr(ExprType.AliphaticElement, atom.AtomicNumber)); } else { expr.And(new Expr(ExprType.IsAliphatic)); } } else if (optset.Contains(ExprType.Element)) { expr.And(new Expr(ExprType.Element, atom.AtomicNumber)); } } } } if (optset.Contains(ExprType.Degree)) { expr.And(new Expr(ExprType.Degree, atom.Bonds.Count)); } if (optset.Contains(ExprType.TotalDegree)) { expr.And(new Expr(ExprType.Degree, atom.Bonds.Count + atom.ImplicitHydrogenCount.Value)); } if (optset.Contains(ExprType.IsInRing) || optset.Contains(ExprType.IsInChain)) { expr.And(new Expr(atom.IsInRing ? ExprType.IsInRing : ExprType.IsInChain)); } if (optset.Contains(ExprType.ImplicitHCount)) { expr.And(new Expr(ExprType.ImplicitHCount)); } if (optset.Contains(ExprType.RingBondCount)) { int rbonds = 0; foreach (var bond in mol.GetConnectedBonds(atom)) { if (bond.IsInRing) { rbonds++; } } expr.And(new Expr(ExprType.RingBondCount, rbonds)); } if (optset.Contains(ExprType.FormalCharge) && atom.FormalCharge != null) { expr.And(new Expr(ExprType.FormalCharge, atom.FormalCharge.Value)); } if (stereos.TryGetValue(atom, out IStereoElement <IChemObject, IChemObject> se) && se.Class == StereoClass.Tetrahedral && optset.Contains(ExprType.Stereochemistry)) { expr.And(new Expr(ExprType.Stereochemistry, (int)se.Configure)); qstereo.Add(se); } var qatom = new QueryAtom(expr); // backward compatibility for naughty methods that are expecting // these to be set for a query! if (optset.Contains(ExprType.Element) || optset.Contains(ExprType.AromaticElement) || optset.Contains(ExprType.AliphaticElement)) { qatom.Symbol = atom.Symbol; } if (optset.Contains(ExprType.AromaticElement) || optset.Contains(ExprType.IsAromatic)) { qatom.IsAromatic = atom.IsAromatic; } mapping.Add(atom, qatom); query.Atoms.Add(qatom); } foreach (var bond in mol.Bonds) { var expr = new Expr(); if (bond.IsAromatic && (optset.Contains(ExprType.SingleOrAromatic) || optset.Contains(ExprType.DoubleOrAromatic) || optset.Contains(ExprType.IsAromatic))) { expr.And(new Expr(ExprType.IsAromatic)); } else if ((optset.Contains(ExprType.SingleOrAromatic) || optset.Contains(ExprType.DoubleOrAromatic) || optset.Contains(ExprType.AliphaticOrder)) && !bond.IsAromatic) { expr.And(new Expr(ExprType.AliphaticOrder, bond.Order.Numeric())); } else if (bond.IsAromatic && optset.Contains(ExprType.IsAliphatic)) { expr.And(new Expr(ExprType.IsAliphatic)); } else if (optset.Contains(ExprType.Order)) { expr.And(new Expr(ExprType.Order, bond.Order.Numeric())); } if (optset.Contains(ExprType.IsInRing) && bond.IsInRing) { expr.And(new Expr(ExprType.IsInRing)); } else if (optset.Contains(ExprType.IsInChain) && !bond.IsInRing) { expr.And(new Expr(ExprType.IsInChain)); } if (stereos.TryGetValue(bond, out IStereoElement <IChemObject, IChemObject> se) && optset.Contains(ExprType.Stereochemistry)) { expr.And(new Expr(ExprType.Stereochemistry, (int)se.Configure)); qstereo.Add(se); } var qbond = new QueryBond(mapping.Get(bond.Begin), mapping.Get(bond.End), expr); // backward compatibility for naughty methods that are expecting // these to be set for a query! if (optset.Contains(ExprType.AliphaticOrder) || optset.Contains(ExprType.Order)) { qbond.Order = bond.Order; } if (optset.Contains(ExprType.SingleOrAromatic) || optset.Contains(ExprType.DoubleOrAromatic) || optset.Contains(ExprType.IsAromatic)) { qbond.IsAromatic = bond.IsAromatic; } mapping.Add(bond, qbond); query.Bonds.Add(qbond); } foreach (var se in qstereo) { query.StereoElements.Add((IStereoElement <IChemObject, IChemObject>)se.Clone(mapping)); } return(query); }