/// <summary>
        /// Tries to saturate a bond by increasing its bond orders by 1.0.
        /// </summary>
        /// <returns>true if the bond could be increased</returns>
        public bool SaturateByIncreasingBondOrder(IBond bond, IAtomContainer atomContainer)
        {
            var atoms   = BondManipulator.GetAtomArray(bond);
            var atom    = atoms[0];
            var partner = atoms[1];

            Debug.WriteLine("  saturating bond: ", atom.Symbol, "-", partner.Symbol);
            var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol);
            var atomTypes2 = structgenATF.GetAtomTypes(partner.Symbol);

            foreach (var aType1 in atomTypes1)
            {
                Debug.WriteLine($"  considering atom type: {aType1}");
                if (CouldMatchAtomType(atomContainer, atom, aType1))
                {
                    Debug.WriteLine($"  trying atom type: {aType1}");
                    foreach (var aType2 in atomTypes2)
                    {
                        Debug.WriteLine($"  considering partner type: {aType1}");
                        if (CouldMatchAtomType(atomContainer, partner, aType2))
                        {
                            Debug.WriteLine($"    with atom type: {aType2}");
                            if (BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) &&
                                BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder))
                            {
                                bond.Order = BondManipulator.IncreaseBondOrder(bond.Order);
                                Debug.WriteLine($"Bond order now {bond.Order}");
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
Exemple #2
0
        /// <summary>
        /// Saturate atom by adjusting its bond orders.
        /// This method is known to fail, especially on pyrrole-like compounds.
        /// Consider using <see cref="Smiles.DeduceBondSystemTool"/>, which should work better
        /// </summary>
        public bool NewSaturate(IBond bond, IAtomContainer atomContainer)
        {
            var atoms   = BondManipulator.GetAtomArray(bond);
            var atom    = atoms[0];
            var partner = atoms[1];

            Debug.WriteLine($"  saturating bond: {atom.Symbol}-{partner.Symbol}");
            var  atomTypes1         = structgenATF.GetAtomTypes(atom.Symbol);
            var  atomTypes2         = structgenATF.GetAtomTypes(partner.Symbol);
            bool bondOrderIncreased = true;

            while (bondOrderIncreased && !IsSaturated(bond, atomContainer))
            {
                Debug.WriteLine("Can increase bond order");
                bondOrderIncreased = false;
                foreach (var aType1 in atomTypes1)
                {
                    if (bondOrderIncreased)
                    {
                        break;
                    }
                    Debug.WriteLine($"  considering atom type: {aType1}");
                    if (CouldMatchAtomType(atomContainer, atom, aType1))
                    {
                        Debug.WriteLine($"  trying atom type: {aType1}");
                        foreach (var aType2 in atomTypes2)
                        {
                            if (bondOrderIncreased)
                            {
                                break;
                            }
                            Debug.WriteLine($"  considering partner type: {aType1}");
                            if (CouldMatchAtomType(atomContainer, partner, aType2))
                            {
                                Debug.WriteLine($"    with atom type: {aType2}");
                                if (!BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) ||
                                    !BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder))
                                {
                                    Debug.WriteLine("Bond order not increased: atoms has reached (or exceeded) maximum bond order for this atom type");
                                }
                                else if (BondManipulator.IsLowerOrder(bond.Order, aType2.MaxBondOrder) &&
                                         BondManipulator.IsLowerOrder(bond.Order, aType1.MaxBondOrder))
                                {
                                    BondManipulator.IncreaseBondOrder(bond);
                                    Debug.WriteLine($"Bond order now {bond.Order}");
                                    bondOrderIncreased = true;
                                }
                            }
                        }
                    }
                }
            }
            return(IsSaturated(bond, atomContainer));
        }
 /// <summary>
 /// This method decides the highest bond order that the bond can have and set
 /// it to that.
 /// </summary>
 /// <param name="bond">The bond to be investigated</param>
 /// <param name="atomContainer">The <see cref="IAtomContainer"/> that contains the bond</param>
 /// <exception cref="CDKException">when the bond cannot be further increased</exception>
 private void SetMaxBondOrder(IBond bond, IAtomContainer atomContainer)
 {
     if (BondOrderCanBeIncreased(bond, atomContainer))
     {
         if (bond.Order != BondOrder.Quadruple)
         {
             bond.Order = BondManipulator.IncreaseBondOrder(bond.Order);
         }
         else
         {
             throw new CDKException("Can't increase a quadruple bond!");
         }
     }
 }
Exemple #4
0
        public virtual void TestGetBondOrderSum()
        {
            IChemObject obj = NewChemObject();
            IRing       r   = obj.Builder.NewRing(5, "C");

            Assert.AreEqual(5, r.GetBondOrderSum());

            BondManipulator.IncreaseBondOrder(r.Bonds[0]);
            Assert.AreEqual(6, r.GetBondOrderSum());

            BondManipulator.IncreaseBondOrder(r.Bonds[0]);
            Assert.AreEqual(7, r.GetBondOrderSum());

            BondManipulator.IncreaseBondOrder(r.Bonds[4]);
            Assert.AreEqual(8, r.GetBondOrderSum());
        }
Exemple #5
0
        /// <summary>
        /// Initiates the process for the given mechanism. The atoms to apply are mapped between
        /// reactants and products.
        /// </summary>
        /// <param name="atomContainerSet"></param>
        /// <param name="atomList">
        /// The list of atoms taking part in the mechanism. Only allowed two atoms.
        ///                    The first atom is the atom which contains the ISingleElectron and the second
        ///                    third is the atom which will be removed
        ///                    the first atom</param>
        /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed one bond.
        ///                       It is the bond which is moved</param>
        /// <returns>The Reaction mechanism</returns>
        public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList)
        {
            var atMatcher = CDK.AtomTypeMatcher;

            if (atomContainerSet.Count != 1)
            {
                throw new CDKException("RadicalSiteIonizationMechanism only expects one IAtomContainer");
            }
            if (atomList.Count != 3)
            {
                throw new CDKException("RadicalSiteIonizationMechanism expects three atoms in the List");
            }
            if (bondList.Count != 2)
            {
                throw new CDKException("RadicalSiteIonizationMechanism only expect one bond in the List");
            }
            IAtomContainer molecule = atomContainerSet[0];
            IAtomContainer reactantCloned;

            reactantCloned = (IAtomContainer)molecule.Clone();
            IAtom atom1    = atomList[0]; // Atom containing the ISingleElectron
            IAtom atom1C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)];
            IAtom atom2    = atomList[1]; // Atom
            IAtom atom2C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)];
            IAtom atom3    = atomList[2]; // Atom to be saved
            IAtom atom3C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)];
            IBond bond1    = bondList[0]; // Bond to increase the order
            int   posBond1 = molecule.Bonds.IndexOf(bond1);
            IBond bond2    = bondList[1]; // Bond to remove
            int   posBond2 = molecule.Bonds.IndexOf(bond2);

            BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]);
            reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond2]);

            var selectron = reactantCloned.GetConnectedSingleElectrons(atom1C);

            reactantCloned.SingleElectrons.Remove(selectron.Last());
            atom1C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);
            IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C);

            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            atom2C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);
            type = atMatcher.FindMatchingAtomType(reactantCloned, atom2C);
            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            reactantCloned.SingleElectrons.Add(atom2C.Builder.NewSingleElectron(atom3C));
            atom3C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);
            type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C);
            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            IReaction reaction = atom2C.Builder.NewReaction();

            reaction.Reactants.Add(molecule);

            /* mapping */
            foreach (var atom in molecule.Atoms)
            {
                IMapping mapping = atom2C.Builder.NewMapping(atom,
                                                             reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]);
                reaction.Mappings.Add(mapping);
            }

            var moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned);

            foreach (var moleculeP in moleculeSetP)
            {
                reaction.Products.Add(moleculeP);
            }

            return(reaction);
        }
Exemple #6
0
        /// <summary>
        /// Initiates the process for the given mechanism. The atoms to apply are mapped between
        /// reactants and products.
        /// </summary>
        /// <param name="atomContainerSet"></param>
        /// <param name="atomList"> The list of atoms taking part in the mechanism. Only allowed two atoms</param>
        /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed one bond</param>
        /// <returns>The Reaction mechanism</returns>
        public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList)
        {
            var atMatcher = CDK.AtomTypeMatcher;

            if (atomContainerSet.Count != 1)
            {
                throw new CDKException("SharingElectronMechanism only expects one IAtomContainer");
            }
            if (atomList.Count != 2)
            {
                throw new CDKException("SharingElectronMechanism expects two atoms in the List");
            }
            if (bondList.Count != 1)
            {
                throw new CDKException("SharingElectronMechanism only expect one bond in the List");
            }
            IAtomContainer molecule = atomContainerSet[0];
            IAtomContainer reactantCloned;

            reactantCloned = (IAtomContainer)molecule.Clone();
            IAtom atom1    = atomList[0]; // Atom containing the lone pair to share
            IAtom atom1C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)];
            IAtom atom2    = atomList[1]; // Atom to neutralize the deficiency of charge
            IAtom atom2C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)];
            IBond bond1    = bondList[0];
            int   posBond1 = molecule.Bonds.IndexOf(bond1);

            BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]);

            var lonePair = reactantCloned.GetConnectedLonePairs(atom1C);

            reactantCloned.LonePairs.Remove(lonePair.Last());
            int charge = atom1C.FormalCharge.Value;

            atom1C.FormalCharge = charge + 1;

            charge = atom2C.FormalCharge.Value;
            atom2C.FormalCharge = charge - 1;

            atom1C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);

            IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C);

            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            atom2C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);
            type = atMatcher.FindMatchingAtomType(reactantCloned, atom2C);
            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            IReaction reaction = atom2C.Builder.NewReaction();

            reaction.Reactants.Add(molecule);

            /* mapping */
            foreach (var atom in molecule.Atoms)
            {
                IMapping mapping = atom2C.Builder.NewMapping(atom,
                                                             reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]);
                reaction.Mappings.Add(mapping);
            }
            reaction.Products.Add(reactantCloned);

            return(reaction);
        }
Exemple #7
0
        /// <summary>
        /// The method is known to fail for certain compounds. For more information, see
        /// cdk.test.limitations package.
        /// This method is known to fail, especially on pyrrole-like compounds.
        /// Consider using <see cref="Smiles.DeduceBondSystemTool"/>, which should work better
        /// </summary>
        public void Saturate(IAtomContainer atomContainer)
        {
            for (int i = 1; i < 4; i++)
            {
                // handle atoms with degree 1 first and then proceed to higher order
                for (int f = 0; f < atomContainer.Atoms.Count; f++)
                {
                    var atom = atomContainer.Atoms[f];
                    Debug.WriteLine($"symbol: {atom.Symbol}");
                    var atomTypes1 = structgenATF.GetAtomTypes(atom.Symbol);
                    var atomType1  = atomTypes1.FirstOrDefault();
                    if (atomType1 != null)
                    {
                        Debug.WriteLine($"first atom type: {atomType1}");
                        if (atomContainer.GetConnectedBonds(atom).Count() == i)
                        {
                            var hcount = atom.ImplicitHydrogenCount ?? 0;
                            if (atom.IsAromatic &&
                                atomContainer.GetBondOrderSum(atom) < atomType1.BondOrderSum - hcount)
                            {
                                var partners = atomContainer.GetConnectedAtoms(atom);
                                foreach (var partner in partners)
                                {
                                    Debug.WriteLine($"Atom has {partners.Count()} partners");
                                    var atomType2 = structgenATF.GetAtomTypes(partner.Symbol).FirstOrDefault();
                                    if (atomType2 == null)
                                    {
                                        return;
                                    }

                                    hcount = partner.ImplicitHydrogenCount ?? 0;
                                    if (atomContainer.GetBond(partner, atom).IsAromatic &&
                                        atomContainer.GetBondOrderSum(partner) < atomType2.BondOrderSum - hcount)
                                    {
                                        Debug.WriteLine($"Partner has {atomContainer.GetBondOrderSum(partner)}, may have: {atomType2.BondOrderSum}");
                                        var bond = atomContainer.GetBond(atom, partner);
                                        Debug.WriteLine($"Bond order was {bond.Order}");
                                        BondManipulator.IncreaseBondOrder(bond);
                                        Debug.WriteLine($"Bond order now {bond.Order}");
                                        break;
                                    }
                                }
                            }

                            var bondOrderSum              = atomType1.BondOrderSum ?? 0;
                            var hydrogenCount             = atom.ImplicitHydrogenCount ?? 0;
                            var atomContainerBondOrderSum = atomContainer.GetBondOrderSum(atom);

                            if (atomContainerBondOrderSum < bondOrderSum - hydrogenCount)
                            {
                                Debug.WriteLine("Atom has " + atomContainerBondOrderSum + ", may have: " + bondOrderSum);
                                var partners = atomContainer.GetConnectedAtoms(atom);
                                foreach (var partner in partners)
                                {
                                    Debug.WriteLine("Atom has " + partners.Count() + " partners");
                                    var atomType2 = structgenATF.GetAtomTypes(partner.Symbol).FirstOrDefault();
                                    if (atomType2 == null)
                                    {
                                        return;
                                    }

                                    var bos2   = atomType2.BondOrderSum ?? 0;
                                    var hc2    = partner.ImplicitHydrogenCount ?? 0;
                                    var acbos2 = atomContainer.GetBondOrderSum(partner);

                                    if (acbos2 < bos2 - hc2)
                                    {
                                        Debug.WriteLine($"Partner has {acbos2}, may have: {bos2}");
                                        var bond = atomContainer.GetBond(atom, partner);
                                        Debug.WriteLine($"Bond order was {bond.Order}");
                                        BondManipulator.IncreaseBondOrder(bond);
                                        Debug.WriteLine($"Bond order now {bond.Order}");
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Initiates the process for the given mechanism. The atoms to apply are mapped between
        /// reactants and products.
        /// </summary>
        /// <param name="atomContainerSet"></param>
        /// <param name="atomList">The list of atoms taking part in the mechanism. Only allowed two three.
        ///                    The first atom is the atom which must contain the charge to be moved, the second
        ///                    is the atom which is in the middle and the third is the atom which acquires the new charge
        /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed two bond.</param>
        ///                       The first bond is the bond to increase the order and the second is the bond
        ///                       to decrease the order
        ///                       It is the bond which is moved</param>
        /// <returns>The Reaction mechanism</returns>
        public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList)
        {
            var atMatcher = CDK.AtomTypeMatcher;

            if (atomContainerSet.Count != 1)
            {
                throw new CDKException("RearrangementChargeMechanism only expects one IAtomContainer");
            }
            if (atomList.Count != 3)
            {
                throw new CDKException("RearrangementChargeMechanism expects three atoms in the List");
            }
            if (bondList.Count != 2)
            {
                throw new CDKException("RearrangementChargeMechanism only expect one bond in the List");
            }
            IAtomContainer molecule = atomContainerSet[0];
            IAtomContainer reactantCloned;

            reactantCloned = (IAtomContainer)molecule.Clone();
            IAtom atom1    = atomList[0]; // Atom with the charge
            IAtom atom1C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)];
            IAtom atom3    = atomList[2]; // Atom which acquires the charge
            IAtom atom3C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)];
            IBond bond1    = bondList[0]; // Bond with single bond
            int   posBond1 = molecule.Bonds.IndexOf(bond1);
            IBond bond2    = bondList[1]; // Bond with double bond
            int   posBond2 = molecule.Bonds.IndexOf(bond2);

            BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond1]);
            if (bond2.Order == BondOrder.Single)
            {
                reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond2]);
            }
            else
            {
                BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[posBond2]);
            }

            //Depending of the charge moving (radical, + or -) there is a different situation
            if (reactantCloned.GetConnectedSingleElectrons(atom1C).Any())
            {
                var selectron = reactantCloned.GetConnectedSingleElectrons(atom1C);
                reactantCloned.SingleElectrons.Remove(selectron.Last());

                reactantCloned.SingleElectrons.Add(bond2.Builder.NewSingleElectron(atom3C));
            }
            else if (atom1C.FormalCharge > 0)
            {
                int charge = atom1C.FormalCharge.Value;
                atom1C.FormalCharge = charge - 1;

                charge = atom3C.FormalCharge.Value;
                atom3C.FormalCharge = charge + 1;
            }
            else if (atom1C.FormalCharge < 1)
            {
                int charge = atom1C.FormalCharge.Value;
                atom1C.FormalCharge = charge + 1;
                var ln = reactantCloned.GetConnectedLonePairs(atom1C);
                reactantCloned.LonePairs.Remove(ln.Last());
                atom1C.IsAromatic = false;

                charge = atom3C.FormalCharge.Value;
                atom3C.FormalCharge = charge - 1;
                reactantCloned.LonePairs.Add(bond2.Builder.NewLonePair(atom3C));
                atom3C.IsAromatic = false;
            }
            else
            {
                return(null);
            }

            atom1C.Hybridization = Hybridization.Unset;
            atom3C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);

            IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C);

            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C);
            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            IReaction reaction = bond2.Builder.NewReaction();

            reaction.Reactants.Add(molecule);

            /* mapping */
            foreach (var atom in molecule.Atoms)
            {
                IMapping mapping = bond2.Builder.NewMapping(atom,
                                                            reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]);
                reaction.Mappings.Add(mapping);
            }
            if (bond2.Order != BondOrder.Single)
            {
                reaction.Products.Add(reactantCloned);
            }
            else
            {
                IChemObjectSet <IAtomContainer> moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned);
                for (int z = 0; z < moleculeSetP.Count(); z++)
                {
                    reaction.Products.Add((IAtomContainer)moleculeSetP[z]);
                }
            }

            return(reaction);
        }
Exemple #9
0
        /// <summary>
        /// Initiates the process for the given mechanism. The atoms and bonds to apply are mapped between
        /// reactants and products.
        /// </summary>
        /// <param name="atomContainerSet"></param>
        /// <param name="atomList">The list of atoms taking part in the mechanism. Only allowed fourth atoms.</param>
        /// <param name="bondList">The list of bonds taking part in the mechanism. Only allowed two bond.
        ///     The first bond is the bond to decrease the order and the second is the bond to increase the order.
        ///     It is the bond which is moved</param>
        /// <returns>The Reaction mechanism</returns>
        public IReaction Initiate(IChemObjectSet <IAtomContainer> atomContainerSet, IList <IAtom> atomList, IList <IBond> bondList)
        {
            var atMatcher = CDK.AtomTypeMatcher;

            if (atomContainerSet.Count != 1)
            {
                throw new CDKException("TautomerizationMechanism only expects one IAtomContainer");
            }
            if (atomList.Count != 4)
            {
                throw new CDKException("TautomerizationMechanism expects four atoms in the List");
            }
            if (bondList.Count != 3)
            {
                throw new CDKException("TautomerizationMechanism expects three bonds in the List");
            }
            var            molecule = atomContainerSet[0];
            IAtomContainer reactantCloned;

            reactantCloned = (IAtomContainer)molecule.Clone();
            IAtom atom1    = atomList[0]; // Atom to be added the hydrogen
            IAtom atom1C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)];
            IAtom atom2    = atomList[1]; // Atom 2
            IAtom atom2C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)];
            IAtom atom3    = atomList[2]; // Atom 3
            IAtom atom3C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom3)];
            IAtom atom4    = atomList[3]; // hydrogen Atom
            IAtom atom4C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom4)];
            IBond bond1    = bondList[0]; // Bond with double bond
            int   posBond1 = molecule.Bonds.IndexOf(bond1);
            IBond bond2    = bondList[1]; // Bond with single bond
            int   posBond2 = molecule.Bonds.IndexOf(bond2);
            IBond bond3    = bondList[2]; // Bond to be removed
            int   posBond3 = molecule.Bonds.IndexOf(bond3);

            BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[posBond1]);
            BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[posBond2]);
            reactantCloned.Bonds.Remove(reactantCloned.Bonds[posBond3]);
            IBond newBond = molecule.Builder.NewBond(atom1C, atom4C, BondOrder.Single);

            reactantCloned.Bonds.Add(newBond);

            atom1C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);
            IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C);

            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            atom3C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);
            type = atMatcher.FindMatchingAtomType(reactantCloned, atom3C);
            if (type == null || type.AtomTypeName.Equals("X", StringComparison.Ordinal))
            {
                return(null);
            }

            IReaction reaction = atom2C.Builder.NewReaction();

            reaction.Reactants.Add(molecule);

            /* mapping */
            foreach (var atom in molecule.Atoms)
            {
                IMapping mapping = atom2C.Builder.NewMapping(atom,
                                                             reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]);
                reaction.Mappings.Add(mapping);
            }

            reaction.Products.Add(reactantCloned);

            return(reaction);
        }
        /// <summary>
        /// Initiate process.
        /// It is needed to call the addExplicitHydrogensToSatisfyValency
        /// from the class tools.HydrogenAdder.
        /// </summary>
        /// <exception cref="CDKException"> Description of the Exception</exception>
        /// <param name="reactants">reactants of the reaction.</param>
        /// <param name="agents">agents of the reaction (Must be in this case null).</param>
        public IReactionSet Initiate(IChemObjectSet <IAtomContainer> reactants, IChemObjectSet <IAtomContainer> agents)
        {
            CheckInitiateParams(reactants, agents);

            var setOfReactions = reactants.Builder.NewReactionSet();
            var reactant       = reactants[0];

            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactant);

            // if the parameter hasActiveCenter is not fixed yet, set the active centers
            var ipr = base.GetParameterClass(typeof(SetReactionCenter));

            if (ipr != null && !ipr.IsSetParameter)
            {
                SetActiveCenters(reactant);
            }

            var arf     = new AllRingsFinder();
            var ringSet = arf.FindAllRings((IAtomContainer)reactant);

            for (int ir = 0; ir < ringSet.Count; ir++)
            {
                var ring = ringSet[ir];

                //only rings with even number of atoms
                int nrAtoms = ring.Atoms.Count;
                if (nrAtoms % 2 == 0)
                {
                    int nrSingleBonds = 0;
                    foreach (var bond in ring.Bonds)
                    {
                        if (bond.Order == BondOrder.Single)
                        {
                            nrSingleBonds++;
                        }
                    }
                    //if exactly half (nrAtoms/2==nrSingleBonds)
                    if (nrSingleBonds != 0 && nrAtoms / 2 == nrSingleBonds)
                    {
                        bool ringCompletActive = false;
                        foreach (var bond in ring.Bonds)
                        {
                            if (bond.IsReactiveCenter)
                            {
                                ringCompletActive = true;
                            }
                            else
                            {
                                ringCompletActive = false;
                                break;
                            }
                        }
                        if (!ringCompletActive)
                        {
                            continue;
                        }

                        IReaction reaction = reactants.Builder.NewReaction();
                        reaction.Reactants.Add(reactant);

                        IAtomContainer reactantCloned;
                        reactantCloned = (IAtomContainer)reactant.Clone();

                        foreach (var bondi in ring.Bonds)
                        {
                            int bondiP = reactant.Bonds.IndexOf(bondi);
                            if (bondi.Order == BondOrder.Single)
                            {
                                BondManipulator.IncreaseBondOrder(reactantCloned.Bonds[bondiP]);
                            }
                            else
                            {
                                BondManipulator.DecreaseBondOrder(reactantCloned.Bonds[bondiP]);
                            }
                        }

                        reaction.Products.Add(reactantCloned);
                        setOfReactions.Add(reaction);
                    }
                }
            }

            return(setOfReactions);
        }