/// <summary> /// Checks a carbon atom to see if it should be shown. /// </summary> /// <param name="carbonAtom">the carbon atom to check</param> /// <param name="container">the atom container</param> /// <param name="model">the renderer model</param> /// <returns>true if the carbon should be shown</returns> public virtual bool ShowCarbon(IAtom carbonAtom, IAtomContainer container, RendererModel model) { if (model.GetKekuleStructure()) { return(true); } if (carbonAtom.FormalCharge != 0) { return(true); } int connectedBondCount = container.GetConnectedBonds(carbonAtom).Count(); if (connectedBondCount < 1) { return(true); } if ((bool)model.GetShowEndCarbons() && connectedBondCount == 1) { return(true); } if (carbonAtom.GetProperty <bool>(ProblemMarker.ErrorMarker, false)) { return(true); } if (container.GetConnectedSingleElectrons(carbonAtom).Any()) { return(true); } return(false); }
public void TestSetAtomProperties_IAtomContainerSet_Object_Object() { string key = "key"; string value = "value"; MoleculeSetManipulator.SetAtomProperties(som, key, value); Assert.AreEqual(value, atomInMol1.GetProperty <string>(key)); Assert.AreEqual(value, atomInMol2.GetProperty <string>(key)); }
public void TestSetAtomProperties_IChemModel_Object_Object() { string key = "key"; string value = "value"; ChemModelManipulator.SetAtomProperties(chemModel, key, value); Assert.AreEqual(value, atomInMol1.GetProperty <string>(key)); Assert.AreEqual(value, atomInMol2.GetProperty <string>(key)); }
private static int AccessAtomMap(IAtom atom) { var mapidx = atom.GetProperty <int?>(CDKPropertyName.AtomAtomMapping); if (mapidx == null) { return(0); } return(mapidx.Value); }
/// <summary> /// Access the atom invariants for this atom. If the invariants have not been /// set an exception is thrown. /// </summary> /// <param name="atom">the atom to obtain the invariants of</param> /// <returns>the atom invariants for the atom</returns> /// <exception cref="NullReferenceException">thrown if the invariants were not set</exception> internal static SMARTSAtomInvariants Invariants(IAtom atom) { var inv = atom.GetProperty <SMARTSAtomInvariants>(SMARTSAtomInvariants.Key); if (inv == null) { throw new NullReferenceException("Missing SMARTSAtomInvariants - please compute these values before matching."); } return(inv); }
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> /// Convert an CDK <see cref="IAtom"/> to a Beam Atom. The symbol and implicit /// hydrogen count are not optional. If the symbol is not supported by the /// SMILES notation (e.g. 'R1') the element will automatically default to /// Unknown ('*'). /// </summary> /// <param name="a">cdk Atom instance</param> /// <returns>a Beam atom</returns> /// <exception cref="NullReferenceException">the atom had an undefined symbol or implicit hydrogen count</exception> static Beam.IAtom ToBeamAtom(IAtom a, SmiFlavors flavour) { var aromatic = SmiFlavorTool.IsSet(flavour, SmiFlavors.UseAromaticSymbols) && a.IsAromatic; var charge = a.FormalCharge; string symbol = CheckNotNull(a.Symbol, "An atom had an undefined symbol"); var element = Beam.Element.OfSymbol(symbol); if (element == null) { element = Beam.Element.Unknown; } var ab = aromatic ? AtomBuilder.Aromatic(element) : AtomBuilder.Aliphatic(element); // CDK leaves nulls on pseudo atoms - we need to check this special case var hCount = a.ImplicitHydrogenCount; if (element == Beam.Element.Unknown) { ab.NumOfHydrogens(hCount ?? 0); } else { ab.NumOfHydrogens(CheckNotNull(hCount, "One or more atoms had an undefined number of implicit hydrogens")); } if (charge.HasValue) { ab.Charge(charge.Value); } // use the mass number to specify isotope? if (SmiFlavorTool.IsSet(flavour, SmiFlavors.AtomicMass | SmiFlavors.AtomicMassStrict)) { var massNumber = a.MassNumber; if (massNumber != null) { ab.Isotope(massNumber.Value); } } var atomClass = a.GetProperty <int?>(CDKPropertyName.AtomAtomMapping); if (SmiFlavorTool.IsSet(flavour, SmiFlavors.AtomAtomMap) && atomClass != null) { ab.AtomClass(atomClass.Value); } return(ab.Build()); }
public int[] GetCanonicalPermutation(IAtomContainer container) { CanonicalLabeler labeler = new CanonicalLabeler(); labeler.CanonLabel(container); int n = container.Atoms.Count; int[] perm = new int[n]; for (int i = 0; i < n; i++) { IAtom a = container.Atoms[i]; int x = (int)a.GetProperty <long>(InvPair.CanonicalLabelPropertyKey); perm[i] = x - 1; } return(perm); }
/// <summary> /// Access the canonical label for the given tree node's atom. If any component is null /// then <see cref="long.MinValue"/> is return thus sorting that object in lower order. /// </summary> /// <param name="node">a tree node to get the label from</param> /// <returns>canonical label value</returns> private static long Label(TreeNode node) { if (node == null) { return(long.MinValue); } IAtom atom = node.Atom; if (atom == null) { return(long.MinValue); } // cast can be removed in master long label = atom.GetProperty(InvPair.CanonicalLabelPropertyKey, long.MinValue); return(label); }
public override bool Matches(IAtom atom) { ReactionRole?atomRole = atom.GetProperty <ReactionRole?>(CDKPropertyName.ReactionRole); if (atomRole == null) { return(this.role == ReactionRoles.Any); } switch (atomRole.Value) { case ReactionRole.Reactant: return((this.role & ReactionRoles.Reactant) != 0); case ReactionRole.Agent: return((this.role & ReactionRoles.Agent) != 0); case ReactionRole.Product: return((this.role & ReactionRoles.Product) != 0); default: return(false); } }
/// <summary> /// Configures an atom to a mmff94 based atom type /// </summary> /// <param name="atom">atom to be configured</param> /// <param name="hoseCode">the 4 sphere hose code of the atom</param> /// <returns>atom</returns> /// <exception cref="NoSuchAtomTypeException"> atomType is not known</exception> public IAtom ConfigureMMFF94BasedAtom(IAtom atom, string hoseCode, bool isInHetRing) { //Debug.WriteLine("****** Configure MMFF94 AtomType ******"); MMFF94BasedAtomTypePattern atp = new MMFF94BasedAtomTypePattern(); var atomTypePattern = atp.AtomTypePatterns; bool atomTypeFlag = false; string ID = ""; hoseCode = RemoveAromaticityFlagsFromHoseCode(hoseCode); string[] ids = { "C", "Csp2", "C=", "Csp", "CO2M", "CNN+", "C%", "CIM+", "CR4R", "CR3R", "CE4R", "Car", "C5A", "C5B", "C5", "HC", "HO", "HN", "HOCO", "HN=C", "HN2", "HOCC", "HOH", "HOS", "HN+", "HO+", "HO=+", "HP", "O", "O=", "OX", "OM", "O+", "O=+", "OH2", "Oar", "N", "N=C", "NC=C", "NSP", "=N=", "NAZT", "N+", "N2OX", "N3OX", "NC#N", "NO3", "N=O", "NC=O", "NSO", "N+=", "NCN+", "NGD+", "NR%", "NM", "N5M", "NPYD", "NPYL", "NPD+", "N5A", "N5B", "NPOX", "N5OX", "N5+", "N5", "S", "S=C", ">SN", "SO2", "SX", "SO2M", "=SO", "Sthi", "PTET", "P", "-P=C", "F", "CL", "BR", "I", "SI", "CL04", "FE+2", "FE+3","F-", "CL-", "BR-", "LI+", "NA+", "K+", "ZN+2", "CA+2", "CU+1", "CU+2", "MG+2", "Du" }; if (atom is IPseudoAtom) { return(atom); } for (int j = 0; j < atomTypePattern.Count; j++) { var p = atomTypePattern[j]; var mat = p.Match(hoseCode); if (mat.Success) { ID = ids[j]; if (j == 0) {//csp3 if (atom.IsInRing) { p = atomTypePattern[13]; //c beta heteroaromatic ring mat = p.Match(hoseCode); var p2 = atomTypePattern[12]; //c alpha heteroaromatic ring var mat2 = p2.Match(hoseCode); if (mat.Success && isInHetRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[13]; } else if (mat2.Success && isInHetRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[12]; } else if (atom.GetProperty <int>("RING_SIZE").Equals(3) && !atom.IsAromatic) { ID = ids[9];//sp3 3mem rings } else if (atom.GetProperty <int>("RING_SIZE").Equals(4) && !atom.IsAromatic) { ID = ids[8];//sp3 4mem rings } else if (atom.IsAromatic && isInHetRing && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[14];//C in het 5 ring } else if (atom.IsAromatic) { ID = ids[11];//C in benzene, pyroll } } else { p = atomTypePattern[66];//S=C mat = p.Match(hoseCode); if (mat.Success) { ID = ids[66]; } } } else if (j == 1) {//csp2 if (atom.IsInRing) { if (atom.GetProperty <int>("RING_SIZE").Equals(4) && !atom.IsAromatic && !isInHetRing) { ID = ids[29];//C= in 4 ring } } } else if (j == 2) {//csp2 C=Hetatom if (atom.IsInRing && isInHetRing && atom.IsAromatic) { ID = ids[12]; } } else if (j == 36) {//n sp3 //Amid p = atomTypePattern[48]; mat = p.Match(hoseCode); if (mat.Success && !atom.IsInRing) { ID = ids[48]; } p = atomTypePattern[44];//sp3 n-oxide mat = p.Match(hoseCode); if (mat.Success) { ID = ids[44]; } p = atomTypePattern[56];//npyd mat = p.Match(hoseCode); if (atom.IsAromatic) {//id in pyridin, pyrol etc... if (mat.Success && atom.IsAromatic && atom.GetProperty<int>("RING_SIZE").Equals(5)){ if (atom.GetProperty <int>("RING_SIZE").Equals(6) && mat.Success) { ID = ids[56]; } else if (atom.GetProperty <int>("RING_SIZE").Equals(5) && mat.Success) { ID = ids[57]; } else { ID = ids[64]; } } p = atomTypePattern[61];//npyd mat = p.Match(hoseCode); if (atom.IsAromatic) {//id in pyridin, pyrol etc... if (mat.Success && atom.IsAromatic && atom.GetProperty<int>("RING_SIZE").Equals(5)){ if (atom.GetProperty <int>("RING_SIZE").Equals(6) && mat.Success) { ID = ids[61]; } else if (atom.GetProperty <int>("RING_SIZE").Equals(5) && mat.Success) { ID = ids[62]; } else { ID = ids[43]; } } p = atomTypePattern[45];//NC#N mat = p.Match(hoseCode); if (mat.Success) { ID = ids[45]; } } else if (j == 37) { //N=C n in imine p = atomTypePattern[59]; //n beta heteroaromatic ring mat = p.Match(hoseCode); if (atom.IsInRing) { if (mat.Success && isInHetRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[59]; } else if (atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(6)) { ID = ids[56]; } else if (atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[57]; } } p = atomTypePattern[43];//N2OX mat = p.Match(hoseCode); if (mat.Success) { if (atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(6)) { ID = ids[61];//npox } else if (mat.Success && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[62];//n5ox } else { ID = ids[43]; } } } else if (j == 43) {//sp2 n oxide if (atom.IsInRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[62]; } else if (atom.IsInRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(6)) { ID = ids[61]; } } else if (j == 40 || j == 41) {//n in c=n=n or terminal n in azido if (atom.IsInRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[59];//aromatic N 5R alpha } } else if (j == 50) {//n+= if (atom.IsInRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[63];//n5+ } else if (atom.IsInRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(6)) { ID = ids[58];//npd+ } } else if (j == 28) {//O ->furan if (atom.IsInRing && atom.IsAromatic && atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[35]; } } else if (j == 16) { //H-object-> enol p = atomTypePattern[21]; //enol mat = p.Match(hoseCode); if (mat.Success) { ID = ids[21]; } p = atomTypePattern[18];//enol mat = p.Match(hoseCode); if (mat.Success) { ID = ids[18]; } } else if (j == 74) { //P p = atomTypePattern[75]; //-P=C mat = p.Match(hoseCode); if (mat.Success) { ID = ids[75]; } } atomTypeFlag = true; //Debug.WriteLine("Atom Symbol:" + atom.Symbol + " MATCH AtomType> " + ID + " HoseCode>" + hoseCode + " "); break; } //IF } //for end if (atomTypeFlag) { atomTypeFlag = false; return(SetAtom(atom, ID)); } else { throw new NoSuchAtomTypeException("Atom is unkown: Symbol:" + atom.Symbol + " does not MATCH AtomType. HoseCode:" + hoseCode); } }
/// <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)); } }
/// <summary> /// Access to the number of lone-pairs (specified as a property of the atom). /// </summary> /// <param name="atom">the atom to get the lone pairs from</param> /// <returns>number of lone pairs</returns> private static int LonePairCount(IAtom atom) { // XXX: LONE_PAIR_COUNT is not currently set! return(atom.GetProperty <int>(CDKPropertyName.LonePairCount, -1)); }
/// <summary> /// Safely access the reaction role of an atom, returns <see cref="ReactionRole.None"/> if null. /// </summary> /// <param name="atom">atom</param> /// <returns>mapidx, None if undefined</returns> private static ReactionRole Role(IAtom atom) { ReactionRole role = atom.GetProperty <ReactionRole>(CDKPropertyName.ReactionRole, ReactionRole.None); return(role); }
public static string GetCIPDescriptor(this IAtom o) => o.GetProperty <string>(CIPDescriptorPropertyKey);
// Creates a CxSmilesState from a molecule with atom labels, repeat units, multi-center bonds etc private static CxSmilesState GetCxSmilesState(SmiFlavors flavour, IAtomContainer mol) { CxSmilesState state = new CxSmilesState { atomCoords = new List <double[]>(), coordFlag = false }; // set the atom labels, values, and coordinates, // and build the atom->idx map required by other parts var atomidx = new Dictionary <IAtom, int>(); for (int idx = 0; idx < mol.Atoms.Count; idx++) { IAtom atom = mol.Atoms[idx]; if (atom is IPseudoAtom) { if (state.atomLabels == null) { state.atomLabels = new SortedDictionary <int, string>(); } IPseudoAtom pseudo = (IPseudoAtom)atom; if (pseudo.AttachPointNum > 0) { state.atomLabels[idx] = "_AP" + pseudo.AttachPointNum; } else { if (!"*".Equals(pseudo.Label, StringComparison.Ordinal)) { state.atomLabels[idx] = pseudo.Label; } } } object comment = atom.GetProperty <object>(CDKPropertyName.Comment); if (comment != null) { if (state.atomValues == null) { state.atomValues = new SortedDictionary <int, string>(); } state.atomValues[idx] = comment.ToString(); } atomidx[atom] = idx; var p2 = atom.Point2D; var p3 = atom.Point3D; if (SmiFlavorTool.IsSet(flavour, SmiFlavors.Cx2dCoordinates) && p2 != null) { state.atomCoords.Add(new double[] { p2.Value.X, p2.Value.Y, 0 }); state.coordFlag = true; } else if (SmiFlavorTool.IsSet(flavour, SmiFlavors.Cx3dCoordinates) && p3 != null) { state.atomCoords.Add(new double[] { p3.Value.X, p3.Value.Y, p3.Value.Z }); state.coordFlag = true; } else if (SmiFlavorTool.IsSet(flavour, SmiFlavors.CxCoordinates)) { state.atomCoords.Add(new double[3]); } } if (!state.coordFlag) { state.atomCoords = null; } // radicals if (mol.SingleElectrons.Count > 0) { state.atomRads = new SortedDictionary <int, CxSmilesState.Radical>(); foreach (ISingleElectron radical in mol.SingleElectrons) { // 0->1, 1->2, 2->3 if (!state.atomRads.TryGetValue(EnsureNotNull(atomidx[radical.Atom]), out CxSmilesState.Radical val)) { val = CxSmilesState.Radical.Monovalent; } else if (val == CxSmilesState.Radical.Monovalent) { val = CxSmilesState.Radical.Divalent; } else if (val == CxSmilesState.Radical.Divalent) { val = CxSmilesState.Radical.Trivalent; } else if (val == CxSmilesState.Radical.Trivalent) { throw new ArgumentException("Invalid radical state, can not be more than trivalent"); } state.atomRads[atomidx[radical.Atom]] = val; } } var sgroups = mol.GetCtabSgroups(); if (sgroups != null) { state.sgroups = new List <CxSmilesState.PolymerSgroup>(); state.positionVar = new SortedDictionary <int, IList <int> >(); foreach (Sgroup sgroup in sgroups) { switch (sgroup.Type) { // polymer SRU case SgroupType.CtabStructureRepeatUnit: case SgroupType.CtabMonomer: case SgroupType.CtabMer: case SgroupType.CtabCopolymer: case SgroupType.CtabCrossLink: case SgroupType.CtabModified: case SgroupType.CtabMixture: case SgroupType.CtabFormulation: case SgroupType.CtabAnyPolymer: case SgroupType.CtabGeneric: case SgroupType.CtabComponent: case SgroupType.CtabGraft: string supscript = (string)sgroup.GetValue(SgroupKey.CtabConnectivity); state.sgroups.Add(new CxSmilesState.PolymerSgroup(GetSgroupPolymerKey(sgroup), ToAtomIdxs(sgroup.Atoms, atomidx), sgroup.Subscript, supscript)); break; case SgroupType.ExtMulticenter: IAtom beg = null; List <IAtom> ends = new List <IAtom>(); ISet <IBond> bonds = sgroup.Bonds; if (bonds.Count != 1) { throw new ArgumentException("Multicenter Sgroup in inconsistent state!"); } IBond bond = bonds.First(); foreach (IAtom atom in sgroup.Atoms) { if (bond.Contains(atom)) { if (beg != null) { throw new ArgumentException("Multicenter Sgroup in inconsistent state!"); } beg = atom; } else { ends.Add(atom); } } state.positionVar[EnsureNotNull(atomidx[beg])] = ToAtomIdxs(ends, atomidx); break; case SgroupType.CtabAbbreviation: case SgroupType.CtabMultipleGroup: // display shortcuts are not output break; case SgroupType.CtabData: // can be generated but currently ignored break; default: throw new NotSupportedException("Unsupported Sgroup Polymer"); } } } return(state); }
// For substituents attached to macrocycles we may be able to point these in/out // of the ring private bool MacroCycleInversion(AtomPair pair) { foreach (var v in pair.seqAt) { IAtom atom = mol.Atoms[v]; if (!atom.IsInRing || adjList[v].Length == 2) { continue; } if (atom.GetProperty <object>(MacroCycleLayout.MACROCYCLE_ATOM_HINT) == null) { continue; } var acyclic = new List <IBond>(2); var cyclic = new List <IBond>(2); foreach (var w in adjList[v]) { IBond bond = bondMap[v, w]; if (bond.IsInRing) { cyclic.Add(bond); } else { acyclic.Add(bond); } } if (cyclic.Count > 2) { continue; } foreach (var bond in acyclic) { if (bfix.Contains(bond)) { continue; } Arrays.Fill(visited, false); stackBackup.len = Visit(visited, stackBackup.xs, v, idxs[bond.GetOther(atom)], 0); Vector2 a = atom.Point2D.Value; Vector2 b = bond.GetOther(atom).Point2D.Value; Vector2 perp = new Vector2(b.X - a.X, b.Y - a.Y); perp = Vector2.Normalize(perp); double score = congestion.Score(); BackupCoords(backup, stackBackup); Reflect(stackBackup, new Vector2(a.X - perp.Y, a.Y + perp.X), new Vector2(a.X + perp.Y, a.Y - perp.X)); congestion.Update(visited, stackBackup.xs, stackBackup.len); if (PercDiff(score, congestion.Score()) >= ImprovementPrecThreshold) { return(true); } RestoreCoords(stackBackup, backup); } } return(false); }
/// <summary> /// Attempt to reduce congestion through rotation of flippable bonds between /// congest pairs. /// </summary> /// <param name="pairs">congested pairs of atoms</param> void Rotate(ICollection <AtomPair> pairs) { // bond has already been tried in this phase so // don't need to test again var tried = new HashSet <IBond>(); foreach (var pair in pairs) { foreach (var bond in pair.bndAt) { // only try each bond once per phase and skip if (!tried.Add(bond)) { continue; } if (bfix.Contains(bond)) { continue; } // those we have found to probably be symmetric if (probablySymmetric.Contains(bond)) { continue; } // can't rotate these if (bond.Order != BondOrder.Single || bond.IsInRing) { continue; } IAtom beg = bond.Begin; IAtom end = bond.End; int begIdx = idxs[beg]; int endIdx = idxs[end]; // terminal if (adjList[begIdx].Length == 1 || adjList[endIdx].Length == 1) { continue; } int begPriority = beg.GetProperty <int>(AtomPlacer.Priority); int endPriority = end.GetProperty <int>(AtomPlacer.Priority); Arrays.Fill(visited, false); if (begPriority < endPriority) { stackBackup.len = VisitAdj(visited, stackBackup.xs, begIdx, endIdx); // avoid moving fixed atoms if (afix.Any()) { int begCnt = NumFixedMoved(stackBackup.xs, stackBackup.len); if (begCnt > 0) { Arrays.Fill(visited, false); stackBackup.len = VisitAdj(visited, stackBackup.xs, endIdx, begIdx); int endCnt = NumFixedMoved(stackBackup.xs, stackBackup.len); if (endCnt > 0) { continue; } } } } else { stackBackup.len = VisitAdj(visited, stackBackup.xs, endIdx, begIdx); // avoid moving fixed atoms if (afix.Any()) { int endCnt = NumFixedMoved(stackBackup.xs, stackBackup.len); if (endCnt > 0) { Arrays.Fill(visited, false); stackBackup.len = VisitAdj(visited, stackBackup.xs, begIdx, endIdx); int begCnt = NumFixedMoved(stackBackup.xs, stackBackup.len); if (begCnt > 0) { continue; } } } } double min = congestion.Score(); BackupCoords(backup, stackBackup); Reflect(stackBackup, beg, end); congestion.Update(visited, stackBackup.xs, stackBackup.len); double delta = min - congestion.Score(); // keep if decent improvement or improvement and resolves this overlap if (delta > RotateDeltaThreshold || (delta > 1 && congestion.Contribution(pair.fst, pair.snd) < MinScore)) { goto continue_Pair; } else { // almost no difference from flipping... bond is probably symmetric // mark to avoid in future iterations if (Math.Abs(delta) < 0.1) { probablySymmetric.Add(bond); } // restore RestoreCoords(stackBackup, backup); congestion.Update(visited, stackBackup.xs, stackBackup.len); congestion.score = min; } } } continue_Pair: ; }
/// <summary> /// Read a Reaction from a file in MDL RXN format /// </summary> /// <returns>The Reaction that was read from the MDL file.</returns> private IReaction ReadReaction(IChemObjectBuilder builder) { IReaction reaction = builder.NewReaction(); try { input.ReadLine(); // first line should be $RXN input.ReadLine(); // second line input.ReadLine(); // third line input.ReadLine(); // fourth line } catch (IOException exception) { Debug.WriteLine(exception); throw new CDKException("Error while reading header of RXN file", exception); } int reactantCount = 0; int productCount = 0; int agentCount = 0; try { string countsLine = input.ReadLine(); // this line contains the number of reactants and products var tokenizer = Strings.Tokenize(countsLine).GetEnumerator(); tokenizer.MoveNext(); reactantCount = int.Parse(tokenizer.Current, NumberFormatInfo.InvariantInfo); Trace.TraceInformation("Expecting " + reactantCount + " reactants in file"); tokenizer.MoveNext(); productCount = int.Parse(tokenizer.Current, NumberFormatInfo.InvariantInfo); if (tokenizer.MoveNext()) { agentCount = int.Parse(tokenizer.Current, NumberFormatInfo.InvariantInfo); // ChemAxon extension, technically BIOVIA now support this but // not documented yet if (ReaderMode == ChemObjectReaderMode.Strict && agentCount > 0) { throw new CDKException("RXN files uses agent count extension"); } } Trace.TraceInformation("Expecting " + productCount + " products in file"); } catch (Exception exception) { if (exception is IOException | exception is FormatException) { Debug.WriteLine(exception); throw new CDKException("Error while counts line of RXN file", exception); } throw; } // now read the reactants try { for (int i = 1; i <= reactantCount; i++) { var molFile = new StringBuilder(); input.ReadLine(); // announceMDLFileLine string molFileLine = ""; do { molFileLine = input.ReadLine(); molFile.Append(molFileLine); molFile.Append('\n'); } while (!string.Equals(molFileLine, "M END", StringComparison.Ordinal)); // read MDL molfile content // Changed this to mdlv2000 reader MDLV2000Reader reader = new MDLV2000Reader(new StringReader(molFile.ToString()), base.ReaderMode); IAtomContainer reactant = (IAtomContainer)reader.Read(builder.NewAtomContainer()); reader.Close(); // add reactant reaction.Reactants.Add(reactant); } } catch (CDKException) { // rethrow exception from MDLReader throw; } catch (Exception exception) { if (exception is IOException | exception is ArgumentException) { Debug.WriteLine(exception); throw new CDKException("Error while reading products", exception); } throw; } // now read the products try { for (int i = 1; i <= agentCount; i++) { var molFile = new StringBuilder(); input.ReadLine(); // String announceMDLFileLine = string molFileLine = ""; do { molFileLine = input.ReadLine(); molFile.Append(molFileLine); molFile.Append('\n'); } while (!string.Equals(molFileLine, "M END", StringComparison.Ordinal)); // read MDL molfile content MDLV2000Reader reader = new MDLV2000Reader(new StringReader(molFile.ToString())); IAtomContainer product = (IAtomContainer)reader.Read(builder.NewAtomContainer()); reader.Close(); // add reactant reaction.Agents.Add(product); } } catch (CDKException) { // rethrow exception from MDLReader throw; } catch (Exception exception) { if (exception is IOException | exception is ArgumentException) { Debug.WriteLine(exception); throw new CDKException("Error while reading reactant", exception); } throw; } // now read the products try { for (int i = 1; i <= productCount; i++) { var molFile = new StringBuilder(); input.ReadLine(); // string announceMDLFileLine = string molFileLine = ""; do { molFileLine = input.ReadLine(); molFile.Append(molFileLine); molFile.Append('\n'); } while (!string.Equals(molFileLine, "M END", StringComparison.Ordinal)); // read MDL molfile content MDLV2000Reader reader = new MDLV2000Reader(new StringReader(molFile.ToString())); IAtomContainer product = (IAtomContainer)reader.Read(builder.NewAtomContainer()); reader.Close(); // add reactant reaction.Products.Add(product); } } catch (CDKException) { // rethrow exception from MDLReader throw; } catch (Exception exception) { if (exception is IOException | exception is ArgumentException) { Debug.WriteLine(exception); throw new CDKException("Error while reading products", exception); } throw; } // now try to map things, if wanted Trace.TraceInformation("Reading atom-atom mapping from file"); // distribute all atoms over two AtomContainer's IAtomContainer reactingSide = builder.NewAtomContainer(); foreach (var molecule in reaction.Reactants) { reactingSide.Add(molecule); } IAtomContainer producedSide = builder.NewAtomContainer(); foreach (var molecule in reaction.Products) { producedSide.Add(molecule); } // map the atoms int mappingCount = 0; // IAtom[] reactantAtoms = reactingSide.GetAtoms(); // IAtom[] producedAtoms = producedSide.GetAtoms(); for (int i = 0; i < reactingSide.Atoms.Count; i++) { for (int j = 0; j < producedSide.Atoms.Count; j++) { IAtom eductAtom = reactingSide.Atoms[i]; IAtom productAtom = producedSide.Atoms[j]; if (eductAtom.GetProperty <object>(CDKPropertyName.AtomAtomMapping) != null && eductAtom.GetProperty <object>(CDKPropertyName.AtomAtomMapping).Equals( productAtom.GetProperty <object>(CDKPropertyName.AtomAtomMapping))) { reaction.Mappings.Add(builder.NewMapping(eductAtom, productAtom)); mappingCount++; break; } } } Trace.TraceInformation("Mapped atom pairs: " + mappingCount); return(reaction); }
/// <summary> /// Safely access the mapidx of an atom, returns 0 if null. /// </summary> /// <param name="atom">atom</param> /// <returns>mapidx, 0 if undefined</returns> private static int Mapidx(IAtom atom) { int mapidx = atom.GetProperty <int>(CDKPropertyName.AtomAtomMapping, 0); return(mapidx); }
/// <summary> /// Configures an atom to a mm2 based atom type /// </summary> /// <param name="atom">atom to be configured</param> /// <param name="hoseCode">the 4 sphere hose code of the atom</param> /// <returns>atom</returns> /// <exception cref="NoSuchAtomTypeException"> atomType is not known</exception> public IAtom ConfigureMM2BasedAtom(IAtom atom, string hoseCode, bool hetRing) { //Debug.WriteLine("CONFIGURE MM2 ATOM"); MM2BasedAtomTypePattern atp = new MM2BasedAtomTypePattern(); var atomTypePattern = atp.AtomTypePatterns; string ID = ""; bool atomTypeFlag = false; if (atom is IPseudoAtom) { return(atom); } hoseCode = RemoveAromaticityFlagsFromHoseCode(hoseCode); string[] ids = { "C", "Csp2", "C=", "Csp", "HC", "O", "O=", "N", "Nsp2", "Nsp", "F", "CL", "BR", "I", "S", "S+", ">SN", "SO2", "SI", "LP", "HO", "CR3R", "HN", "HOCO", "P", "B", "BTET", "HN2", "C.", "C+", "GE", "SN", "PB", "SE", "TE", "D", "NPYD", "CE3R", "N+", "NPYL", "Oar", "Sthi", "N2OX", "HS", "=N=", "NO3", "OM", "HN+", "OR", "Car", "HE", "NE", "AR", "KR", "XE", "", "", "", "MG", "PTET", "FE", "FE", "NI","NI", "CO", "CO", "", "", "OX", "OK", "C++", "N=C", "NPD+", "N+=", "N2OX" }; for (int j = 0; j < atomTypePattern.Count; j++) { Regex p = atomTypePattern[j]; var mat = p.Match(hoseCode); if (mat.Success) { ID = ids[j]; //CHECK Rings 1,2,8,9? Thiole 44? AZO 9? Radical - ? Amid 23/enol 21? if (j == 0) { //csp3 if (atom.IsInRing) { if (atom.GetProperty <int>("RING_SIZE").Equals(3)) { ID = ids[21]; } else if (atom.GetProperty <int>("RING_SIZE").Equals(6) && atom.IsAromatic) { ID = ids[1]; } else if (atom.IsAromatic) { ID = ids[1]; } } } else if (j == 1) { //csp2 if (atom.IsInRing) { if (atom.GetProperty <int>("RING_SIZE").Equals(6) && atom.IsAromatic) { } else if (atom.GetProperty <int>("RING_SIZE").Equals(3)) { ID = ids[37]; } else { ID = ids[1]; } } p = atomTypePattern[2]; //COOH mat = p.Match(hoseCode); if (mat.Success && !atom.IsInRing) { ID = ids[2]; } } else if (j == 5) { //OH/Ether if (atom.IsInRing) { if (atom.GetProperty <int>("RING_SIZE").Equals(3)) { ID = ids[48]; //EPOXY } else if (atom.GetProperty <int>("RING_SIZE").Equals(5) && atom.IsAromatic) { ID = ids[40]; } else { ID = ids[5]; } } } else if (j == 7) { //n sp3 if (atom.IsInRing && atom.IsAromatic) { if (atom.GetProperty <int>("RING_SIZE").Equals(5)) { ID = ids[39]; } } //Amid p = atomTypePattern[77]; mat = p.Match(hoseCode); if (mat.Success && !atom.IsInRing) { ID = ids[8]; } } else if (j == 8) { //nsp2 if (atom.IsInRing) { if (atom.GetProperty <int>("RING_SIZE").Equals(6)) { ID = ids[36]; } } p = atomTypePattern[36]; //AZO mat = p.Match(hoseCode); if (mat.Success && !atom.IsInRing) { ID = ids[36]; } } else if (j == 43) { //h thiol var d_tmp = atom.GetProperty <double>("MAX_BOND_ORDER"); if (d_tmp > 1) { ID = ids[4]; } } else if (j == 20) { //h alcohol,ether p = atomTypePattern[76]; //Enol mat = p.Match(hoseCode); if (mat.Success && !atom.IsInRing) { ID = ids[27]; } p = atomTypePattern[23]; //COOH mat = p.Match(hoseCode); if (mat.Success && !atom.IsInRing) { ID = ids[23]; } } else if (j == 22) { p = atomTypePattern[75]; //Amid mat = p.Match(hoseCode); if (mat.Success) { ID = ids[27]; } } atomTypeFlag = true; //Debug.WriteLine("Atom Symbol:" + atom.Symbol + " MATCH AtomType> " + ID + " HoseCode>" + hoseCode + " "); break; } //IF } //for end if (atomTypeFlag) { atomTypeFlag = false; return(SetAtom(atom, ID)); } else { throw new NoSuchAtomTypeException("Atom is unkown: Symbol:" + atom.Symbol + " does not MATCH AtomType. HoseCode:" + hoseCode); } }
/// <summary> /// Converts an 'inlined' reaction stored in a molecule back to a reaction. /// </summary> /// <param name="mol">molecule to convert</param> /// <returns>reaction</returns> /// <seealso cref="ToMolecule(IReaction)"/> public static IReaction ToReaction(IAtomContainer mol) { if (mol == null) { throw new ArgumentException("Null molecule provided"); } var bldr = mol.Builder; var rxn = bldr.NewReaction(); rxn.SetProperties(mol.GetProperties()); rxn.Id = mol.Id; var components = new Dictionary <int, IAtomContainer>(); // split atoms foreach (var atom in mol.Atoms) { var role = atom.GetProperty <ReactionRole?>(CDKPropertyName.ReactionRole); var grpIdx = atom.GetProperty <int?>(CDKPropertyName.ReactionGroup); if (role == null || role.Value == ReactionRole.None) { throw new ArgumentException("Atom " + mol.Atoms.IndexOf(atom) + " had undefined role"); } if (grpIdx == null) { throw new ArgumentException("Atom " + mol.Atoms.IndexOf(atom) + " had no reaction group id"); } // new component, and add to appropriate role if (!components.TryGetValue(grpIdx.Value, out IAtomContainer comp)) { components[grpIdx.Value] = comp = bldr.NewAtomContainer(); switch (role) { case ReactionRole.Reactant: rxn.Reactants.Add(comp); break; case ReactionRole.Product: rxn.Products.Add(comp); break; case ReactionRole.Agent: rxn.Agents.Add(comp); break; } } comp.Atoms.Add(atom); } // split bonds foreach (var bond in mol.Bonds) { var beg = bond.Begin; var end = bond.End; var begIdx = beg.GetProperty <int?>(CDKPropertyName.ReactionGroup); var endIdx = end.GetProperty <int?>(CDKPropertyName.ReactionGroup); if (begIdx == null || endIdx == null) { throw new ArgumentException("Bond " + mol.Bonds.IndexOf(bond) + " had atoms with no reaction group id"); } if (!begIdx.Equals(endIdx)) { throw new ArgumentException("Bond " + mol.Bonds.IndexOf(bond) + " had atoms with different reaction group id"); } components[begIdx.Value].Bonds.Add(bond); } // split stereochemistry foreach (var se in mol.StereoElements) { IAtom focus = null; switch (se) { case ITetrahedralChirality tc: focus = tc.ChiralAtom; break; case IDoubleBondStereochemistry ds: focus = ds.StereoBond.Begin; break; case ExtendedTetrahedral et: focus = et.Focus; break; } if (focus == null) { throw new ArgumentException("Stereochemistry had no focus"); } var grpIdx = focus.GetProperty <int>(CDKPropertyName.ReactionGroup); components[grpIdx].StereoElements.Add(se); } foreach (var se in mol.SingleElectrons) { var grpIdx = se.Atom.GetProperty <int>(CDKPropertyName.ReactionGroup); components[grpIdx].SingleElectrons.Add(se); } foreach (var lp in mol.LonePairs) { var grpIdx = lp.Atom.GetProperty <int>(CDKPropertyName.ReactionGroup); components[grpIdx].LonePairs.Add(lp); } return(rxn); }