예제 #1
0
        public static IAtomContainer GetLargestMoleculeFragment(
            IAtomContainer mol,
            out int acc)
        {
            IAtomContainer mol2, molMain = null;

            acc = 0;
            if (mol == null)
            {
                return(null);
            }

            if (ConnectivityChecker.IsConnected(mol))
            {
                acc = 1;
                return(mol);
            }

            IReadOnlyList <IAtomContainer> acs = ConnectivityChecker.PartitionIntoMolecules(mol);
            int largestAc = -1;

            acc = acs.Count;
            for (int aci = 0; aci < acc; aci++)
            {
                mol2 = acs[aci];
                int ac2 = mol2.Atoms.Count;
                if (ac2 > largestAc)
                {
                    largestAc = mol2.Atoms.Count;
                    molMain   = mol2;
                }
            }

            return(molMain);
        }
예제 #2
0
        /// <summary>
        /// </summary>
        /// <param name="mol"></param>
        /// <param name="mcss"></param>
        /// <param name="shouldMatchBonds"></param>
        /// <returns>IMolecule Set</returns>
        /// <exception cref="CDKException"></exception>
        private static IChemObjectSet <IAtomContainer> GetUncommon(IAtomContainer mol, IAtomContainer mcss, bool shouldMatchBonds)
        {
            List <int> atomSerialsToDelete = new List <int>();

            var matches = CDKMCS.GetSubgraphAtomsMaps(mol, mcss, shouldMatchBonds);
            var mapList = matches[0];

            foreach (var o in mapList)
            {
                CDKRMap rmap = (CDKRMap)o;
                atomSerialsToDelete.Add(rmap.Id1);
            }

            // at this point we have the serial numbers of the bonds to delete
            // we should get the actual bonds rather than delete by serial numbers
            List <IAtom> atomsToDelete = new List <IAtom>();

            foreach (var serial in atomSerialsToDelete)
            {
                atomsToDelete.Add(mol.Atoms[serial]);
            }

            // now lets get rid of the bonds themselves
            foreach (var atom in atomsToDelete)
            {
                mol.RemoveAtomAndConnectedElectronContainers(atom);
            }

            // now we probably have a set of disconnected components
            // so lets get a set of individual atom containers for
            // corresponding to each component
            return(ConnectivityChecker.PartitionIntoMolecules(mol));
        }
예제 #3
0
        public void TestTwentyRandomStructures()
        {
            var            molecule = TestMoleculeFactory.MakeAlphaPinene();
            var            rg       = new RandomGenerator(molecule);
            IAtomContainer result   = null;

            for (int f = 0; f < 50; f++)
            {
                result = rg.ProposeStructure();
                Assert.AreEqual(molecule.Atoms.Count, result.Atoms.Count);
                Assert.AreEqual(1, ConnectivityChecker.PartitionIntoMolecules(result).Count());
            }
        }
예제 #4
0
        /// <summary>
        /// Fragment a molecule
        /// </summary>
        /// <param name="mol"></param>
        /// <returns></returns>

        public static List <KeyValuePair <string, IAtomContainer> > FragmentMoleculeAndCanonicalizeSmiles(
            IAtomContainer mol,
            bool filterOutCommonCounterIons)
        {
            int aci, fi, i1;

            KeyValuePair <string, IAtomContainer>         kvp;
            List <KeyValuePair <string, IAtomContainer> > frags = new List <KeyValuePair <string, IAtomContainer> >();

            if (mol == null)
            {
                return(frags);
            }

            IReadOnlyList <IAtomContainer> acs = ConnectivityChecker.PartitionIntoMolecules(mol);

            int acc = acs.Count;

            for (aci = 0; aci < acc; aci++)
            {
                IAtomContainer fragMol    = acs[aci];
                string         fragSmiles = AtomContainerToSmiles(fragMol);
                if (filterOutCommonCounterIons)
                {
                    if (CommonSmallFragments.Contains(fragSmiles) ||
                        GetHeavyAtomCount(fragMol) <= 6)
                    {
                        continue;
                    }
                }

                kvp = new KeyValuePair <string, IAtomContainer>(fragSmiles, fragMol);

                int ac = fragMol.Atoms.Count;

                for (fi = frags.Count - 1; fi >= 0; fi--)                 // insert into list so that fragments are ordered largest to smallest
                {
                    if (frags[fi].Value.Atoms.Count >= ac)
                    {
                        break;
                    }
                }
                frags.Insert(fi + 1, kvp);
            }

            return(frags);
        }
예제 #5
0
        /// <summary>
        /// Modules for cleaning a molecule
        /// </summary>
        /// <param name="molecule"></param>
        /// <returns>cleaned AtomContainer</returns>
        public static IAtomContainer CheckAndCleanMolecule(IAtomContainer molecule)
        {
            bool isMarkush = false;

            foreach (var atom in molecule.Atoms)
            {
                if (atom.Symbol.Equals("R", StringComparison.Ordinal))
                {
                    isMarkush = true;
                    break;
                }
            }

            if (isMarkush)
            {
                Console.Error.WriteLine("Skipping Markush structure for sanity check");
            }

            // Check for salts and such
            if (!ConnectivityChecker.IsConnected(molecule))
            {
                // lets see if we have just two parts if so, we assume its a salt and just work
                // on the larger part. Ideally we should have a check to ensure that the smaller
                //  part is a metal/halogen etc.
                var fragments = ConnectivityChecker.PartitionIntoMolecules(molecule).ToReadOnlyList();
                if (fragments.Count > 2)
                {
                    Console.Error.WriteLine("More than 2 components. Skipped");
                }
                else
                {
                    var frag1 = fragments[0];
                    var frag2 = fragments[1];
                    if (frag1.Atoms.Count > frag2.Atoms.Count)
                    {
                        molecule = frag1;
                    }
                    else
                    {
                        molecule = frag2;
                    }
                }
            }
            Configure(molecule);
            return(molecule);
        }
 public static void RemoveElectronContainer(IChemObjectSet <IAtomContainer> set, IElectronContainer electrons)
 {
     foreach (var atomContainer in set)
     {
         if (atomContainer.Contains(electrons))
         {
             atomContainer.Remove(electrons);
             var molecules = ConnectivityChecker.PartitionIntoMolecules(atomContainer);
             if (molecules.Count > 1)
             {
                 set.Remove(atomContainer);
                 for (int k = 0; k < molecules.Count; k++)
                 {
                     set.Add(molecules[k]);
                 }
             }
             return;
         }
     }
 }
예제 #7
0
        private static int GetFragmentCount(IAtomContainer molecule)
        {
            bool fragmentFlag   = true;
            var  fragmentMolSet = ChemObjectBuilder.Instance.NewAtomContainerSet();
            int  countFrag      = 0;

            if (molecule.Atoms.Count > 0)
            {
                fragmentFlag = ConnectivityChecker.IsConnected(molecule);
                if (!fragmentFlag)
                {
                    fragmentMolSet.AddRange(ConnectivityChecker.PartitionIntoMolecules(molecule));
                }
                else
                {
                    fragmentMolSet.Add(molecule);
                }
                countFrag = fragmentMolSet.Count;
            }
            return(countFrag);
        }
예제 #8
0
        /// <summary>
        /// Determine the ring set for this atom container.
        /// </summary>
        /// <param name="atomContainer">the atom container to find rings in.</param>
        /// <returns>the rings of the molecule</returns>
        protected virtual IRingSet GetRingSet(IAtomContainer atomContainer)
        {
            IRingSet ringSet = atomContainer.Builder.NewRingSet();

            try
            {
                var molecules = ConnectivityChecker.PartitionIntoMolecules(atomContainer);
                foreach (var mol in molecules)
                {
                    ringSet.Add(Cycles.FindSSSR(mol).ToRingSet());
                }

                return(ringSet);
            }
            catch (Exception exception)
            {
                Trace.TraceWarning("Could not partition molecule: " + exception.Message);
                Debug.WriteLine(exception);
                return(ringSet);
            }
        }
예제 #9
0
        /// <summary>
        /// Generates a shortest path based BitArray fingerprint for the given AtomContainer.
        /// </summary>
        /// <param name="ac">The AtomContainer for which a fingerprint is generated</param>
        /// <exception cref="CDKException">if there error in aromaticity perception or other CDK functions</exception>
        /// <returns>A <see cref="BitArray"/> representing the fingerprint</returns>
        public override IBitFingerprint GetBitFingerprint(IAtomContainer ac)
        {
            IAtomContainer atomContainer = null;

            atomContainer = (IAtomContainer)ac.Clone();
            Aromaticity.CDKLegacy.Apply(atomContainer);
            var bitSet = new BitArray(fingerprintLength);

            if (!ConnectivityChecker.IsConnected(atomContainer))
            {
                var partitionedMolecules = ConnectivityChecker.PartitionIntoMolecules(atomContainer);
                foreach (var container in partitionedMolecules)
                {
                    AddUniquePath(container, bitSet);
                }
            }
            else
            {
                AddUniquePath(atomContainer, bitSet);
            }
            return(new BitSetFingerprint(bitSet));
        }
예제 #10
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);
        }
예제 #11
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 receives the charge and the second the single electron</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 = CDKAtomTypeMatcher.GetInstance(CDKAtomTypeMatcher.Mode.RequireExplicitHydrogens);

            if (atomContainerSet.Count != 1)
            {
                throw new CDKException("RemovingSEofBMechanism only expects one IAtomContainer");
            }
            if (atomList.Count != 2)
            {
                throw new CDKException("RemovingSEofBMechanism expects two atoms in the List");
            }
            if (bondList.Count != 1)
            {
                throw new CDKException("RemovingSEofBMechanism only expects one bond in the List");
            }
            var molecule       = atomContainerSet[0];
            var reactantCloned = (IAtomContainer)molecule.Clone();
            var atom1          = atomList[0];
            var atom1C         = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)];
            var atom2          = atomList[1];
            var atom2C         = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)];
            var bond1          = bondList[0];
            var posBond1       = molecule.Bonds.IndexOf(bond1);

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

            var charge = atom1C.FormalCharge.Value;

            atom1C.FormalCharge = charge + 1;
            reactantCloned.SingleElectrons.Add(atom1C.Builder.NewSingleElectron(atom2C));

            // check if resulting atom type is reasonable
            atom1C.Hybridization = Hybridization.Unset;
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);
            var 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);
            }

            var reaction = atom1C.Builder.NewReaction();

            reaction.Reactants.Add(molecule);

            /* mapping */
            foreach (var atom in molecule.Atoms)
            {
                IMapping mapping = atom1C.Builder.NewMapping(atom,
                                                             reactantCloned.Atoms[molecule.Atoms.IndexOf(atom)]);
                reaction.Mappings.Add(mapping);
            }
            if (bond1.Order != BondOrder.Single)
            {
                reaction.Products.Add(reactantCloned);
            }
            else
            {
                var moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned);
                foreach (var moleculeP in moleculeSetP)
                {
                    reaction.Products.Add(moleculeP);
                }
            }

            return(reaction);
        }
예제 #12
0
        /// <summary>
        /// Find all enabled abbreviations in the provided molecule. They are not
        /// added to the existing Sgroups and may need filtering.
        /// </summary>
        /// <param name="mol">molecule</param>
        /// <returns>list of new abbreviation Sgroups</returns>
        public IList <Sgroup> Generate(IAtomContainer mol)
        {
            // mark which atoms have already been abbreviated or are
            // part of an existing Sgroup
            var usedAtoms = new HashSet <IAtom>();
            var sgroups   = mol.GetCtabSgroups();

            if (sgroups != null)
            {
                foreach (var sgroup in sgroups)
                {
                    foreach (var atom in sgroup.Atoms)
                    {
                        usedAtoms.Add(atom);
                    }
                }
            }

            var newSgroups = new List <Sgroup>();

            // disconnected abbreviations, salts, common reagents, large compounds
            if (!usedAtoms.Any())
            {
                try
                {
                    var    copy   = AtomContainerManipulator.CopyAndSuppressedHydrogens(mol);
                    string cansmi = usmigen.Create(copy);
                    if (disconnectedAbbreviations.TryGetValue(cansmi, out string label) && !disabled.Contains(label) && ContractToSingleLabel)
                    {
                        var sgroup = new Sgroup
                        {
                            Type      = SgroupType.CtabAbbreviation,
                            Subscript = label
                        };
                        foreach (var atom in mol.Atoms)
                        {
                            sgroup.Atoms.Add(atom);
                        }
                        return(new[] { sgroup });
                    }
                    else if (cansmi.Contains("."))
                    {
                        var parts = ConnectivityChecker.PartitionIntoMolecules(mol);

                        // leave one out
                        Sgroup best = null;
                        for (int i = 0; i < parts.Count; i++)
                        {
                            var a = parts[i];
                            var b = a.Builder.NewAtomContainer();
                            for (int j = 0; j < parts.Count; j++)
                            {
                                if (j != i)
                                {
                                    b.Add(parts[j]);
                                }
                            }
                            var sgroup1 = GetAbbr(a);
                            var sgroup2 = GetAbbr(b);
                            if (sgroup1 != null && sgroup2 != null && ContractToSingleLabel)
                            {
                                var combined = new Sgroup();
                                label = null;
                                foreach (var atom in sgroup1.Atoms)
                                {
                                    combined.Atoms.Add(atom);
                                }
                                foreach (var atom in sgroup2.Atoms)
                                {
                                    combined.Atoms.Add(atom);
                                }
                                if (sgroup1.Subscript.Length > sgroup2.Subscript.Length)
                                {
                                    combined.Subscript = sgroup1.Subscript + String_Interpunct + sgroup2.Subscript;
                                }
                                else
                                {
                                    combined.Subscript = sgroup2.Subscript + String_Interpunct + sgroup1.Subscript;
                                }
                                combined.Type = SgroupType.CtabAbbreviation;
                                return(new[] { combined });
                            }
                            if (sgroup1 != null && (best == null || sgroup1.Atoms.Count > best.Atoms.Count))
                            {
                                best = sgroup1;
                            }
                            if (sgroup2 != null && (best == null || sgroup2.Atoms.Count < best.Atoms.Count))
                            {
                                best = sgroup2;
                            }
                        }
                        if (best != null)
                        {
                            newSgroups.Add(best);
                            foreach (var atom in best.Atoms)
                            {
                                usedAtoms.Add(atom);
                            }
                        }
                    }
                }
                catch (CDKException)
                {
                }
            }

            var fragments  = GenerateFragments(mol);
            var sgroupAdjs = new MultiDictionary <IAtom, Sgroup>();

            foreach (var frag in fragments)
            {
                try
                {
                    var smi = usmigen.Create(AtomContainerManipulator.CopyAndSuppressedHydrogens(frag));
                    if (!connectedAbbreviations.TryGetValue(smi, out string label) || disabled.Contains(label))
                    {
                        continue;
                    }

                    bool overlap = false;

                    // note: first atom is '*'
                    var numAtoms = frag.Atoms.Count;
                    var numBonds = frag.Bonds.Count;
                    for (int i = 1; i < numAtoms; i++)
                    {
                        if (usedAtoms.Contains(frag.Atoms[i]))
                        {
                            overlap = true;
                            break;
                        }
                    }

                    // overlaps with previous assignment
                    if (overlap)
                    {
                        continue;
                    }

                    // create new abbreviation Sgroup
                    var sgroup = new Sgroup
                    {
                        Type      = SgroupType.CtabAbbreviation,
                        Subscript = label
                    };

                    var   attachBond = frag.Bonds[0].GetProperty <IBond>(PropertyName_CutBond);
                    IAtom attachAtom = null;
                    sgroup.Bonds.Add(attachBond);
                    for (int i = 1; i < numAtoms; i++)
                    {
                        var atom = frag.Atoms[i];
                        usedAtoms.Add(atom);
                        sgroup.Atoms.Add(atom);
                        if (attachBond.Begin.Equals(atom))
                        {
                            attachAtom = attachBond.End;
                        }
                        else if (attachBond.End.Equals(atom))
                        {
                            attachAtom = attachBond.Begin;
                        }
                    }

                    if (attachAtom != null)
                    {
                        sgroupAdjs.Add(attachAtom, sgroup);
                    }
                    newSgroups.Add(sgroup);
                }
                catch (CDKException)
                {
                    // ignore
                }
            }

            if (!ContractOnHetero)
            {
                return(newSgroups);
            }

            // now collapse
            foreach (var attach in mol.Atoms)
            {
                if (usedAtoms.Contains(attach))
                {
                    continue;
                }

                // skip charged or isotopic labelled, C or R/*, H, He
                if ((attach.FormalCharge != null && attach.FormalCharge != 0) ||
                    attach.MassNumber != null ||
                    attach.AtomicNumber == 6 ||
                    attach.AtomicNumber < 2)
                {
                    continue;
                }

                var hcount   = attach.ImplicitHydrogenCount.Value;
                var xatoms   = new HashSet <IAtom>();
                var xbonds   = new HashSet <IBond>();
                var newbonds = new HashSet <IBond>();
                xatoms.Add(attach);

                var nbrSymbols = new List <string>();
                var todelete   = new HashSet <Sgroup>();
                foreach (var sgroup in sgroupAdjs[attach])
                {
                    if (ContainsChargeChar(sgroup.Subscript))
                    {
                        continue;
                    }
                    if (sgroup.Bonds.Count != 1)
                    {
                        continue;
                    }
                    var xbond = sgroup.Bonds.First();
                    xbonds.Add(xbond);
                    foreach (var a in sgroup.Atoms)
                    {
                        xatoms.Add(a);
                    }
                    if (attach.Symbol.Length == 1 &&
                        char.IsLower(sgroup.Subscript[0]))
                    {
                        if (ChemicalElement.OfSymbol(attach.Symbol + sgroup.Subscript[0]) != ChemicalElement.R)
                        {
                            goto continue_collapse;
                        }
                    }
                    nbrSymbols.Add(sgroup.Subscript);
                    todelete.Add(sgroup);
                }
                int numSGrpNbrs = nbrSymbols.Count;
                foreach (var bond in mol.GetConnectedBonds(attach))
                {
                    if (!xbonds.Contains(bond))
                    {
                        var nbr = bond.GetOther(attach);
                        // contract terminal bonds
                        if (mol.GetConnectedBonds(nbr).Count() == 1)
                        {
                            if (nbr.MassNumber != null ||
                                (nbr.FormalCharge != null && nbr.FormalCharge != 0))
                            {
                                newbonds.Add(bond);
                            }
                            else if (nbr.AtomicNumber == 1)
                            {
                                hcount++;
                                xatoms.Add(nbr);
                            }
                            else if (nbr.AtomicNumber > 0)
                            {
                                nbrSymbols.Add(NewSymbol(nbr.AtomicNumber, nbr.ImplicitHydrogenCount.Value, false));
                                xatoms.Add(nbr);
                            }
                        }
                        else
                        {
                            newbonds.Add(bond);
                        }
                    }
                }

                // reject if no symbols
                // reject if no bonds (<1), except if all symbols are identical... (HashSet.size==1)
                // reject if more that 2 bonds
                if (!nbrSymbols.Any() ||
                    newbonds.Count < 1 && (new HashSet <string>(nbrSymbols).Count != 1) ||
                    newbonds.Count > 2)
                {
                    continue;
                }

                // create the symbol
                var sb = new StringBuilder();
                sb.Append(NewSymbol(attach.AtomicNumber, hcount, newbonds.Count == 0));
                string prev  = null;
                int    count = 0;
                nbrSymbols.Sort((o1, o2) =>
                {
                    int cmp = o1.Length.CompareTo(o2.Length);
                    if (cmp != 0)
                    {
                        return(cmp);
                    }
                    return(o1.CompareTo(o2));
                });
                foreach (string nbrSymbol in nbrSymbols)
                {
                    if (nbrSymbol.Equals(prev))
                    {
                        count++;
                    }
                    else
                    {
                        bool useParen = count == 0 || CountUpper(prev) > 1 || (prev != null && nbrSymbol.StartsWith(prev));
                        AppendGroup(sb, prev, count, useParen);
                        prev  = nbrSymbol;
                        count = 1;
                    }
                }
                AppendGroup(sb, prev, count, false);

                // remove existing
                foreach (var e in todelete)
                {
                    newSgroups.Remove(e);
                }

                // create new
                var newSgroup = new Sgroup
                {
                    Type      = SgroupType.CtabAbbreviation,
                    Subscript = sb.ToString()
                };
                foreach (var bond in newbonds)
                {
                    newSgroup.Bonds.Add(bond);
                }
                foreach (var atom in xatoms)
                {
                    newSgroup.Atoms.Add(atom);
                }

                newSgroups.Add(newSgroup);
                foreach (var a in xatoms)
                {
                    usedAtoms.Add(a);
                }
continue_collapse:
                ;
            }

            return(newSgroups);
        }
예제 #13
0
        /// <summary>
        /// Performs the n point crossover of two <see cref="IAtomContainer"/>.
        /// </summary>
        /// <remarks>
        /// Precondition: The atoms in the molecules are ordered by properties to
        /// preserve (e. g. atom symbol). Due to its randomized nature, this method
        /// fails in around 3% of all cases. A <see cref="CDKException"/> with message "Could not
        /// mate these properly" will then be thrown.
        /// </remarks>
        /// <returns>The children.</returns>
        /// <exception cref="CDKException">if it was not possible to form off springs.</exception>
        public IReadOnlyList <IAtomContainer> DoCrossover(IAtomContainer dad, IAtomContainer mom)
        {
            int tries = 0;

            while (true)
            {
                int dim       = dad.Atoms.Count;
                var redChild  = new IAtomContainer[2];
                var blueChild = new IAtomContainer[2];

                var redAtoms  = new List <int>();
                var blueAtoms = new List <int>();

                // randomly divide atoms into two parts: redAtoms and blueAtoms.
                if (splitMode == SplitMode.Random)
                {
                    // better way to randomly divide atoms into two parts: redAtoms
                    // and blueAtoms.
                    for (int i = 0; i < dim; i++)
                    {
                        redAtoms.Add(i);
                    }
                    for (int i = 0; i < (dim - numatoms); i++)
                    {
                        int ranInt = RandomNumbersTool.RandomInt(0, redAtoms.Count - 1);
                        redAtoms.RemoveAt(ranInt);
                        blueAtoms.Add(ranInt);
                    }
                }
                else
                {
                    // split graph using depth/breadth first traverse
                    var graph = new ChemGraph(dad)
                    {
                        NumAtoms = numatoms
                    };
                    if (splitMode == SplitMode.DepthFirst)
                    {
                        redAtoms = graph.PickDFGraph().ToList();
                    }
                    else
                    {
                        //this is SPLIT_MODE_BREADTH_FIRST
                        redAtoms = graph.PickBFGraph().ToList();
                    }

                    for (int i = 0; i < dim; i++)
                    {
                        int element = i;
                        if (!(redAtoms.Contains(element)))
                        {
                            blueAtoms.Add(element);
                        }
                    }
                }
                /* * dividing over ** */
                redChild[0]  = dad.Builder.NewAtomContainer(dad);
                blueChild[0] = dad.Builder.NewAtomContainer(dad);
                redChild[1]  = dad.Builder.NewAtomContainer(mom);
                blueChild[1] = dad.Builder.NewAtomContainer(mom);

                var blueAtomsInRedChild0 = new List <IAtom>();
                for (int j = 0; j < blueAtoms.Count; j++)
                {
                    blueAtomsInRedChild0.Add(redChild[0].Atoms[(int)blueAtoms[j]]);
                }
                for (int j = 0; j < blueAtomsInRedChild0.Count; j++)
                {
                    redChild[0].RemoveAtom(blueAtomsInRedChild0[j]);
                }
                var blueAtomsInRedChild1 = new List <IAtom>();
                for (int j = 0; j < blueAtoms.Count; j++)
                {
                    blueAtomsInRedChild1.Add(redChild[1].Atoms[(int)blueAtoms[j]]);
                }
                for (int j = 0; j < blueAtomsInRedChild1.Count; j++)
                {
                    redChild[1].RemoveAtom(blueAtomsInRedChild1[j]);
                }
                var redAtomsInBlueChild0 = new List <IAtom>();
                for (int j = 0; j < redAtoms.Count; j++)
                {
                    redAtomsInBlueChild0.Add(blueChild[0].Atoms[(int)redAtoms[j]]);
                }
                for (int j = 0; j < redAtomsInBlueChild0.Count; j++)
                {
                    blueChild[0].RemoveAtom(redAtomsInBlueChild0[j]);
                }
                var redAtomsInBlueChild1 = new List <IAtom>();
                for (int j = 0; j < redAtoms.Count; j++)
                {
                    redAtomsInBlueChild1.Add(blueChild[1].Atoms[(int)redAtoms[j]]);
                }
                for (int j = 0; j < redAtomsInBlueChild1.Count; j++)
                {
                    blueChild[1].RemoveAtom(redAtomsInBlueChild1[j]);
                }
                //if the two fragments of one and only one parent have an uneven number
                //of attachment points, we need to rearrange them
                var    satCheck         = CDK.SaturationChecker;
                double red1attachpoints = 0;
                for (int i = 0; i < redChild[0].Atoms.Count; i++)
                {
                    red1attachpoints += satCheck.GetCurrentMaxBondOrder(redChild[0].Atoms[i], redChild[0]);
                }
                double red2attachpoints = 0;
                for (int i = 0; i < redChild[1].Atoms.Count; i++)
                {
                    red2attachpoints += satCheck.GetCurrentMaxBondOrder(redChild[1].Atoms[i], redChild[1]);
                }
                bool isok = true;
                if (red1attachpoints % 2 == 1 ^ red2attachpoints % 2 == 1)
                {
                    isok = false;
                    var firstToBalance  = redChild[1];
                    var secondToBalance = blueChild[0];
                    if (red1attachpoints % 2 == 1)
                    {
                        firstToBalance  = redChild[0];
                        secondToBalance = blueChild[1];
                    }
                    //we need an atom which has
                    //- an uneven number of "attachment points" and
                    //- an even number of outgoing bonds
                    foreach (var atom in firstToBalance.Atoms)
                    {
                        if (satCheck.GetCurrentMaxBondOrder(atom, firstToBalance) % 2 == 1 &&
                            firstToBalance.GetBondOrderSum(atom) % 2 == 0)
                        {
                            //we remove this from it's current container and add it to the other one
                            firstToBalance.RemoveAtom(atom);
                            secondToBalance.Atoms.Add(atom);
                            isok = true;
                            break;
                        }
                    }
                }
                //if we have combinable fragments
                if (isok)
                {
                    //combine the fragments crosswise
                    var newstrucs = new IChemObjectSet <IAtomContainer> [2];
                    newstrucs[0] = dad.Builder.NewAtomContainerSet();
                    newstrucs[0].AddRange(ConnectivityChecker.PartitionIntoMolecules(redChild[0]));
                    newstrucs[0].AddRange(ConnectivityChecker.PartitionIntoMolecules(blueChild[1]));
                    newstrucs[1] = dad.Builder.NewAtomContainerSet();
                    newstrucs[1].AddRange(ConnectivityChecker.PartitionIntoMolecules(redChild[1]));
                    newstrucs[1].AddRange(ConnectivityChecker.PartitionIntoMolecules(blueChild[0]));

                    //and merge
                    var children = new List <IAtomContainer>(2);
                    for (int f = 0; f < 2; f++)
                    {
                        var structrue = pfsm.Generate2(newstrucs[f]);
                        if (structrue != null)
                        {
                            //if children are not correct, the outer loop will repeat,
                            //so we ignore this
                            children.Add(structrue);
                        }
                    }
                    if (children.Count == 2 &&
                        ConnectivityChecker.IsConnected(children[0]) &&
                        ConnectivityChecker.IsConnected(children[1]))
                    {
                        return(children);
                    }
                }
                tries++;
                if (tries > 20)
                {
                    throw new CDKException("Could not mate these properly");
                }
            }
        }
예제 #14
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);
        }
예제 #15
0
        /// <summary>
        /// Parse a reaction SMILES.
        /// </summary>
        /// <param name="smiles">The SMILES string to parse</param>
        /// <returns>An instance of <see cref="IReaction"/></returns>
        /// <exception cref="InvalidSmilesException">if the string cannot be parsed</exception>
        /// <seealso cref="ParseSmiles(string)"/>
        public IReaction ParseReactionSmiles(string smiles)
        {
            if (!smiles.Contains(">"))
            {
                throw new InvalidSmilesException("Not a reaction SMILES: " + smiles);
            }

            var first  = smiles.IndexOf('>');
            var second = smiles.IndexOf('>', first + 1);

            if (second < 0)
            {
                throw new InvalidSmilesException("Invalid reaction SMILES:" + smiles);
            }

            var reactants = smiles.Substring(0, first);
            var agents    = smiles.Substring(first + 1, second - (first + 1));
            var products  = smiles.Substring(second + 1, smiles.Length - (second + 1));

            var reaction = builder.NewReaction();

            // add reactants
            if (!(reactants.Count() == 0))
            {
                var reactantContainer = ParseSmiles(reactants, true);
                var reactantSet       = ConnectivityChecker.PartitionIntoMolecules(reactantContainer);
                foreach (var reactant in reactantSet)
                {
                    reaction.Reactants.Add(reactant);
                }
            }

            // add agents
            if (!(agents.Count() == 0))
            {
                var agentContainer = ParseSmiles(agents, true);
                var agentSet       = ConnectivityChecker.PartitionIntoMolecules(agentContainer);
                foreach (var agent in agentSet)
                {
                    reaction.Agents.Add(agent);
                }
            }

            string title = null;

            // add products
            if (!(products.Count() == 0))
            {
                var productContainer = ParseSmiles(products, true);
                var productSet       = ConnectivityChecker.PartitionIntoMolecules(productContainer);
                foreach (var product in productSet)
                {
                    reaction.Products.Add(product);
                }
                reaction.SetProperty(CDKPropertyName.Title, title = productContainer.Title);
            }

            try
            {
                //CXSMILES layer
                ParseRxnCXSMILES(title, reaction);
            }
            catch (Exception e)
            {
                //e.StackTrace
                throw new InvalidSmilesException("Error parsing CXSMILES:" + e.Message);
            }

            return(reaction);
        }
예제 #16
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. Both atoms acquire a ISingleElectron</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("TautomerizationMechanism only expects one IAtomContainer");
            }
            if (atomList.Count != 2)
            {
                throw new CDKException("HomolyticCleavageMechanism expects two atoms in the List");
            }
            if (bondList.Count != 1)
            {
                throw new CDKException("HomolyticCleavageMechanism only expect one bond in the List");
            }
            IAtomContainer molecule = atomContainerSet[0];
            IAtomContainer reactantCloned;

            reactantCloned = (IAtomContainer)molecule.Clone();
            IAtom atom1    = atomList[0];
            IAtom atom1C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom1)];
            IAtom atom2    = atomList[1];
            IAtom atom2C   = reactantCloned.Atoms[molecule.Atoms.IndexOf(atom2)];
            IBond bond1    = bondList[0];
            int   posBond1 = molecule.Bonds.IndexOf(bond1);

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

            reactantCloned.SingleElectrons.Add(bond1.Builder.NewSingleElectron(atom1C));
            reactantCloned.SingleElectrons.Add(bond1.Builder.NewSingleElectron(atom2C));
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(reactantCloned);

            // check if resulting atom type is reasonable
            atom1C.Hybridization = Hybridization.Unset;
            IAtomType type = atMatcher.FindMatchingAtomType(reactantCloned, atom1C);

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

            // check if resulting atom type is reasonable: an acceptor atom cannot be charged positive*/
            atom2C.Hybridization = Hybridization.Unset;
            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);
            }
            if (bond1.Order != BondOrder.Single)
            {
                reaction.Products.Add(reactantCloned);
            }
            else
            {
                var moleculeSetP = ConnectivityChecker.PartitionIntoMolecules(reactantCloned);
                foreach (var moleculeP in moleculeSetP)
                {
                    reaction.Products.Add(moleculeP);
                }
            }

            return(reaction);
        }
예제 #17
0
        /// <summary>
        /// BuildFingerprints
        /// </summary>
        public static void BuildFingerprints(
            UniChemData icd)
        {
            IAtomContainer mol, mol2;
            InChIGenerator ig = null;
            int            acc, aci, ci;

            icd.Children.Clear();

            string parentFIKHB = icd.GetFIKHB();

            DateTime t0 = DateTime.Now;

            mol = CdkMol.InChIToAtomContainer(icd.InChIString);

            icd.CanonSmiles = CdkMol.AtomContainerToSmiles(mol);

            InChIToAtomContainerTime += TimeOfDay.Delta(ref t0);

            BitSetFingerprint fp =             // generate a fingerprint
                                   CdkFingerprint.BuildBitSetFingerprint(mol, FingerprintType.MACCS, -1, -1);

            BuildFinterprintTime1 += TimeOfDay.Delta(ref t0);

            icd.Fingerprint = fp;

            if (ConnectivityChecker.IsConnected(mol))
            {
                return;                                                   // single fragment
            }
            InChIGeneratorFactory igf = InChIGeneratorFactory.Instance;

            AtomContainerSet acs = (AtomContainerSet)ConnectivityChecker.PartitionIntoMolecules(mol);

            PartitionIntoMoleculesTime += TimeOfDay.Delta(ref t0);

            acc = acs.Count;

            for (aci = 0; aci < acc; aci++)
            {
                mol2 = acs[aci];
                GetAtomContainerTime += TimeOfDay.Delta(ref t0);

                ig = igf.GetInChIGenerator(mol2);
                if (!IsAcceptableInchiStatus(ig))
                {
                    continue;
                }

                string childKey   = ig.GetInChIKey();
                string childFIKHB = UniChemUtil.GetFIKHB(childKey);
                InChIGeneratorTime += TimeOfDay.Delta(ref t0);

                fp =                 // generate a fingerprint for the fragment
                     CdkFingerprint.BuildBitSetFingerprint(mol2, FingerprintType.MACCS, -1, -1);

                BuildFinterprintTime2 += TimeOfDay.Delta(ref t0);

                for (ci = 0; ci < icd.Children.Count; ci++)                 // see if a dup child
                {
                    if (icd.Children[ci].ChildFIKHB == childFIKHB)
                    {
                        break;
                    }
                }
                if (ci < icd.Children.Count)
                {
                    continue;                                          // skip if dup
                }
                UniChemFIKHBHierarchy fikhbHier = new UniChemFIKHBHierarchy();
                fikhbHier.ParentFIKHB = parentFIKHB;
                fikhbHier.ChildFIKHB  = childFIKHB;
                fikhbHier.CanonSmiles = CdkMol.AtomContainerToSmiles(mol2);
                fikhbHier.Fingerprint = fp;

                icd.Children.Add(fikhbHier);
            }

            return;
        }