Ejemplo n.º 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);
        }
        public void TestPartialFilledStructureMerger2()
        {
            var sp  = CDK.SmilesParser;
            var acs = ChemObjectBuilder.Instance.NewAtomContainerSet();

            acs.Add(sp.ParseSmiles("[C]=[C]CC[CH2]"));
            acs.Add(sp.ParseSmiles("[C]([CH2])=C1CC1"));
            var pfsm   = new PartialFilledStructureMerger();
            var result = pfsm.Generate(acs);

            Assert.IsTrue(ConnectivityChecker.IsConnected(result));
            Assert.IsTrue(CDK.SaturationChecker.IsSaturated(result));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Proposes a structure which can be accepted or rejected by an external
        /// entity. If rejected, the structure is not used as a starting point
        /// for the next random move in structure space.
        /// </summary>
        /// <returns>A proposed molecule</returns>
        public IAtomContainer ProposeStructure()
        {
            Debug.WriteLine("RandomGenerator->ProposeStructure() Start");
            do
            {
                trial = (IAtomContainer)Molecule.Clone();
                Mutate(trial);
                Debug.WriteLine("BondCounts:    " + string.Join(" ", trial.Atoms.Select(n => trial.GetConnectedBonds(n).Count())));
                Debug.WriteLine("BondOrderSums: " + string.Join(" ", trial.Atoms.Select(n => trial.GetBondOrderSum(n))));
            } while (trial == null || !ConnectivityChecker.IsConnected(trial));
            proposedStructure = trial;

            return(proposedStructure);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        // @cdk.bug 1632610
        public void TestCycloButene()
        {
            var mol = parser.ParseSmiles("C=CC=C");

            BODRIsotopeFactory.Instance.ConfigureAtoms(mol);
            AddImplicitHydrogens(mol);

            var structures = VicinitySampler.Sample(mol);
            var count      = 0;

            foreach (var temp in structures)
            {
                Assert.IsNotNull(temp);
                Assert.IsTrue(ConnectivityChecker.IsConnected(temp));
                Assert.AreEqual(mol.Atoms.Count, temp.Atoms.Count);
                count++;
            }
            Assert.AreEqual(1, count);
        }
Ejemplo n.º 6
0
        public void TestVicinitySampler_sample()
        {
            IAtomContainer mol = TestMoleculeFactory.MakeEthylPropylPhenantren();

            BODRIsotopeFactory.Instance.ConfigureAtoms(mol);
            AddImplicitHydrogens(mol);

            var structures = VicinitySampler.Sample(mol);
            var count      = 0;

            foreach (var temp in structures)
            {
                Assert.IsNotNull(temp);
                Assert.IsTrue(ConnectivityChecker.IsConnected(temp));
                Assert.AreEqual(mol.Atoms.Count, temp.Atoms.Count);
                count++;
            }
            Assert.AreEqual(37, count);
        }
Ejemplo n.º 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);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Generates a random structure based on the atoms in the given <see cref="IAtomContainer"/>.
        /// </summary>
        public IAtomContainer Generate()
        {
            int  iteration      = 0;
            bool structureFound = false;

            do
            {
                iteration++;
                atomContainer.RemoveAllElectronContainers();
                bool bondFormed;
                do
                {
                    bondFormed = false;
                    foreach (var atom in atomContainer.Atoms)
                    {
                        if (!satCheck.IsSaturated(atom, atomContainer))
                        {
                            var partner = GetAnotherUnsaturatedNode(atom);
                            if (partner != null)
                            {
                                var cmax1 = satCheck.GetCurrentMaxBondOrder(atom, atomContainer);
                                var cmax2 = satCheck.GetCurrentMaxBondOrder(partner, atomContainer);
                                var max   = Math.Min(cmax1, cmax2);
                                var order = Math.Min(Math.Max(1.0, random.NextInt((int)Math.Round(max))), 3.0);
                                Debug.WriteLine($"Forming bond of order {order}");
                                atomContainer.Bonds.Add(atomContainer.Builder.NewBond(atom, partner, BondManipulator.CreateBondOrder(order)));
                                bondFormed = true;
                            }
                        }
                    }
                } while (bondFormed);
                if (ConnectivityChecker.IsConnected(atomContainer) && satCheck.IsSaturated(atomContainer))
                {
                    structureFound = true;
                }
            } while (!structureFound && iteration < 20);
            Debug.WriteLine($"Structure found after #iterations: {iteration}");
            return(atomContainer.Builder.NewAtomContainer(atomContainer));
        }
Ejemplo n.º 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));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Generate 3D coordinates with force field information.
        /// </summary>
        public IAtomContainer Generate3DCoordinates(IAtomContainer molecule, bool clone)
        {
            var originalAtomTypeNames = molecule.Atoms.Select(n => n.AtomTypeName).ToArray();

            Debug.WriteLine("******** GENERATE COORDINATES ********");
            foreach (var atom in molecule.Atoms)
            {
                atom.IsPlaced  = false;
                atom.IsVisited = false;
            }
            //CHECK FOR CONNECTIVITY!
            Debug.WriteLine($"#atoms>{molecule.Atoms.Count}");
            if (!ConnectivityChecker.IsConnected(molecule))
            {
                throw new CDKException("Molecule is NOT connected, could not layout.");
            }

            // setup helper classes
            AtomPlacer   atomPlacer = new AtomPlacer();
            AtomPlacer3D ap3d       = new AtomPlacer3D(parameterSet);
            AtomTetrahedralLigandPlacer3D atlp3d = new AtomTetrahedralLigandPlacer3D(parameterSet);

            if (clone)
            {
                molecule = (IAtomContainer)molecule.Clone();
            }
            atomPlacer.Molecule = molecule;

            if (ap3d.NumberOfUnplacedHeavyAtoms(molecule) == 1)
            {
                Debug.WriteLine("Only one Heavy Atom");
                ap3d.GetUnplacedHeavyAtom(molecule).Point3D = new Vector3(0.0, 0.0, 0.0);
                try
                {
                    atlp3d.Add3DCoordinatesForSinglyBondedLigands(molecule);
                }
                catch (CDKException ex3)
                {
                    Trace.TraceError($"PlaceSubstitutensERROR: Cannot place substitutents due to:{ex3.Message}");
                    Debug.WriteLine(ex3);
                    throw new CDKException("PlaceSubstitutensERROR: Cannot place substitutents due to:" + ex3.Message,
                                           ex3);
                }
                return(molecule);
            }
            //Assing Atoms to Rings,Aliphatic and Atomtype
            IRingSet ringSetMolecule   = ffc.AssignAtomTyps(molecule);
            IRingSet largestRingSet    = null;
            int      numberOfRingAtoms = 0;

            IReadOnlyList <IRingSet> ringSystems = null;

            if (ringSetMolecule.Count > 0)
            {
                if (templateHandler == null)
                {
                    throw new CDKException("You are trying to generate coordinates for a molecule with rings, but you have no template handler set. Please do SetTemplateHandler() before generation!");
                }
                ringSystems    = RingPartitioner.PartitionRings(ringSetMolecule);
                largestRingSet = RingSetManipulator.GetLargestRingSet(ringSystems);
                IAtomContainer largestRingSetContainer = RingSetManipulator.GetAllInOneContainer(largestRingSet);
                numberOfRingAtoms = largestRingSetContainer.Atoms.Count;
                templateHandler.MapTemplates(largestRingSetContainer, numberOfRingAtoms);
                if (!CheckAllRingAtomsHasCoordinates(largestRingSetContainer))
                {
                    throw new CDKException("RingAtomLayoutError: Not every ring atom is placed! Molecule cannot be layout.");
                }

                SetAtomsToPlace(largestRingSetContainer);
                SearchAndPlaceBranches(molecule, largestRingSetContainer, ap3d, atlp3d, atomPlacer);
                largestRingSet = null;
            }
            else
            {
                //Debug.WriteLine("****** Start of handling aliphatic molecule ******");
                IAtomContainer ac = AtomPlacer.GetInitialLongestChain(molecule);
                SetAtomsToUnVisited(molecule);
                SetAtomsToUnplaced(molecule);
                ap3d.PlaceAliphaticHeavyChain(molecule, ac);
                //ZMatrixApproach
                ap3d.ZMatrixChainToCartesian(molecule, false);
                SearchAndPlaceBranches(molecule, ac, ap3d, atlp3d, atomPlacer);
            }
            LayoutMolecule(ringSystems, molecule, ap3d, atlp3d, atomPlacer);
            //Debug.WriteLine("******* PLACE SUBSTITUENTS ******");
            try
            {
                atlp3d.Add3DCoordinatesForSinglyBondedLigands(molecule);
            }
            catch (CDKException ex3)
            {
                Trace.TraceError($"PlaceSubstitutensERROR: Cannot place substitutents due to:{ex3.Message}");
                Debug.WriteLine(ex3);
                throw new CDKException("PlaceSubstitutensERROR: Cannot place substitutents due to:" + ex3.Message, ex3);
            }
            // restore the original atom type names
            for (int i = 0; i < originalAtomTypeNames.Length; i++)
            {
                molecule.Atoms[i].AtomTypeName = originalAtomTypeNames[i];
            }

            return(molecule);
        }
Ejemplo n.º 11
0
        static INativeMolMx CdkMolUtil => StaticCdkMol.I;         // static molecule shortcut for utility methods

        /// <summary>
        /// Build UniChem Data
        /// Note that this routine takes about 14 secs the first time it's called, faster thereafter.
        /// </summary>
        /// <param name="mol"></param>
        /// <returns></returns>

        public static UniChemData BuildUniChemData(
            IAtomContainer mol)
        {
            IAtomContainer mol2;
            InChIGenerator ig = null;
            string         molSmiles, fragSmiles = "", molFile = "";
            int            acc, fi, ci;

            //if (Lex.StartsWith(molString, "InChI="))
            //{
            //	sourceInchi = molString;
            //	mol = CdkMol.InChIToAtomContainer(sourceInchi);
            //}

            //else // assume molfile otherwise
            //{
            //	molfile = molString;
            //	mol = CdkMol.MolfileToAtomContainer(molfile);
            //}

            if (mol.Atoms.Count <= 1)
            {
                throw new Exception("Atom count <= 1");
            }

            int pseudoCount = CdkMol.RemovePseudoAtoms(mol);

            mol = CdkMol.AtomContainerToSmilesAndBack(mol, out molSmiles);

            InChIGeneratorFactory igf = InChIGeneratorFactory.Instance;

            try
            {
                //string options = "/KET /15T"; // options to include keto-enol and 1,5-tautomerism (not recognized by CDK)
                ig = igf.GetInChIGenerator(mol);                 //, options);
            }

            catch (Exception ex)             // may fail for some complex mols (e.g. CorpId 12345, a MDL V3000 mol with a CF3 Sgroup/alias)
            {
                throw new Exception(ex.Message, ex);
            }

            //{
            //	try // try to simplify the molfile so that InChI can handle it
            //	{
            //		//if (Lex.IsUndefined(molfile)) throw ex;
            //		string molfile2 = SimplifyMolfileForInChIGeneration(molile);
            //		mol = CdkMol.MolfileToAtomContainer(molfile2);
            //		mol = CdkMol.AtomContainerToSmilesAndBack(mol, out molSmiles);
            //		ig = igf.getInChIGenerator(mol);
            //	}
            //	catch (Exception ex2)
            //	{
            //		throw new Exception(ex2.Message, ex);
            //	}
            //}

            if (!IsAcceptableInchiStatus(ig))
            {
                string errMsg = "InChI generation " + ig.ReturnStatus + ": " + ig.Message;
                molFile = CdkMol.AtomContainerToMolfile(mol);                 // debug
                throw new Exception(errMsg);
            }

            // Populate the UniChem object

            UniChemData icd = new UniChemData();

            //icd.Molfile = molfile;
            icd.AtomContainer = mol;
            icd.InChIString   = ig.InChI;
            icd.InChIKey      = ig.GetInChIKey();
            icd.CanonSmiles   = molSmiles;

            // Build and store fingerprint

            mol = CdkMol.InChIToAtomContainer(icd.InChIString);

            //int hydRemovedCnt = CdkMol.RemoveHydrogensBondedToPositiveNitrogens(mol);
            mol = CdkMol.RemoveIsotopesStereoExplicitHydrogens(mol); // additional normalization for fingerprint

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

            icd.Fingerprint = fp;

            if (ConnectivityChecker.IsConnected(mol))
            {
                return(icd);                                                  // single fragment
            }
            //string mf = CdkMol.GetMolecularFormula(mol);

            //AtomContainerSet acs = (AtomContainerSet)ConnectivityChecker.partitionIntoMolecules(mol);
            List <IAtomContainer> frags = CdkMol.FragmentMolecule(mol, true);            // get fragments filtering out small and common frags

            for (fi = 0; fi < frags.Count; fi++)
            {
                mol2 = frags[fi];

                int atomCnt = mol2.Atoms.Count;
                if (atomCnt <= 1)
                {
                    continue;
                }

                try
                {
                    mol2 = CdkMol.AtomContainerToSmilesAndBack(mol2, out fragSmiles);
                }
                catch (Exception ex)
                {
                    AtomContainerToSmilesAndBackErrorCount++;                     // just count error and ignore
                }

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

                string childInChIString = ig.InChI;
                string childInChIKey    = ig.GetInChIKey();
                string childFIKHB       = UniChemUtil.GetFIKHB(childInChIKey);

                mol2 = CdkMol.InChIToAtomContainer(childInChIString);      // convert from inchi
                mol2 = CdkMol.RemoveIsotopesStereoExplicitHydrogens(mol2); // additional normalization for fingerprint

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

                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 icdChild = new UniChemFIKHBHierarchy();
                icdChild.ParentFIKHB = icd.GetFIKHB();
                icdChild.ChildFIKHB  = childFIKHB;
                icdChild.InChIString = childInChIString;
                icdChild.CanonSmiles = fragSmiles;

                icdChild.Fingerprint = fp;

                icd.Children.Add(icdChild);
            }

            return(icd);
        }
Ejemplo n.º 12
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;
        }
Ejemplo n.º 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");
                }
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Choose any possible quadruple of the set of atoms
        /// in ac and establish all of the possible bonding schemes according to
        /// Faulon's equations.
        /// </summary>
        public static IEnumerable <IAtomContainer> Sample(IAtomContainer ac)
        {
            Debug.WriteLine("RandomGenerator->Mutate() Start");

            int    nrOfAtoms = ac.Atoms.Count;
            double a11 = 0, a12 = 0, a22 = 0, a21 = 0;
            double b11 = 0, lowerborder = 0, upperborder = 0;
            double b12 = 0;
            double b21 = 0;
            double b22 = 0;

            double[]       cmax  = new double[4];
            double[]       cmin  = new double[4];
            IAtomContainer newAc = null;

            IAtom ax1 = null, ax2 = null, ay1 = null, ay2 = null;
            IBond b1 = null, b2 = null, b3 = null, b4 = null;
            //int[] choices = new int[3];
            /* We need at least two non-zero bonds in order to be successful */
            int nonZeroBondsCounter = 0;

            for (int x1 = 0; x1 < nrOfAtoms; x1++)
            {
                for (int x2 = x1 + 1; x2 < nrOfAtoms; x2++)
                {
                    for (int y1 = x2 + 1; y1 < nrOfAtoms; y1++)
                    {
                        for (int y2 = y1 + 1; y2 < nrOfAtoms; y2++)
                        {
                            nonZeroBondsCounter = 0;
                            ax1 = ac.Atoms[x1];
                            ay1 = ac.Atoms[y1];
                            ax2 = ac.Atoms[x2];
                            ay2 = ac.Atoms[y2];

                            /* Get four bonds for these four atoms */

                            b1 = ac.GetBond(ax1, ay1);
                            if (b1 != null)
                            {
                                a11 = BondManipulator.DestroyBondOrder(b1.Order);
                                nonZeroBondsCounter++;
                            }
                            else
                            {
                                a11 = 0;
                            }

                            b2 = ac.GetBond(ax1, ay2);
                            if (b2 != null)
                            {
                                a12 = BondManipulator.DestroyBondOrder(b2.Order);
                                nonZeroBondsCounter++;
                            }
                            else
                            {
                                a12 = 0;
                            }

                            b3 = ac.GetBond(ax2, ay1);
                            if (b3 != null)
                            {
                                a21 = BondManipulator.DestroyBondOrder(b3.Order);
                                nonZeroBondsCounter++;
                            }
                            else
                            {
                                a21 = 0;
                            }

                            b4 = ac.GetBond(ax2, ay2);
                            if (b4 != null)
                            {
                                a22 = BondManipulator.DestroyBondOrder(b4.Order);
                                nonZeroBondsCounter++;
                            }
                            else
                            {
                                a22 = 0;
                            }
                            if (nonZeroBondsCounter > 1)
                            {
                                // Compute the range for b11 (see Faulons formulae for details)

                                cmax[0]     = 0;
                                cmax[1]     = a11 - a22;
                                cmax[2]     = a11 + a12 - 3;
                                cmax[3]     = a11 + a21 - 3;
                                cmin[0]     = 3;
                                cmin[1]     = a11 + a12;
                                cmin[2]     = a11 + a21;
                                cmin[3]     = a11 - a22 + 3;
                                lowerborder = MathTools.Max(cmax);
                                upperborder = MathTools.Min(cmin);
                                for (b11 = lowerborder; b11 <= upperborder; b11++)
                                {
                                    if (b11 != a11)
                                    {
                                        b12 = a11 + a12 - b11;
                                        b21 = a11 + a21 - b11;
                                        b22 = a22 - a11 + b11;
                                        Debug.WriteLine("Trying atom combination : " + x1 + ":" + x2 + ":" + y1 + ":" + y2);
                                        newAc = (IAtomContainer)ac.Clone();
                                        Change(newAc, x1, y1, x2, y2, b11, b12, b21, b22);
                                        if (ConnectivityChecker.IsConnected(newAc))
                                        {
                                            yield return(newAc);
                                        }
                                        else
                                        {
                                            Debug.WriteLine("not connected");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            yield break;
        }
Ejemplo n.º 15
0
        [TestCategory("VerySlowTest")] // structgen is slow... a single method here currently takes ~6 seconds
        public void TestDoCrossover_IAtomContainer()
        {
            IChemObjectSet <IAtomContainer> som;

            var filename = "NCDK.Data.Smiles.c10h16isomers.smi";

            using (var ins = ResourceLoader.GetAsStream(filename))
                using (SMILESReader reader = new SMILESReader(ins))
                {
                    som = reader.Read(CDK.Builder.NewAtomContainerSet());
                    Assert.AreEqual(99, som.Count, "We must have read 99 structures");
                }

            // Comment out next line to enable time seed random.
            RandomNumbersTool.RandomSeed = 0L;

            CrossoverMachine cm             = new CrossoverMachine();
            string           correctFormula = "C10H16";
            int errorcount = 0;

            for (int i = 0; i < som.Count; i++)
            {
                int[] hydrogencount1 = new int[4];
                foreach (var atom in som[i].Atoms)
                {
                    hydrogencount1[atom.ImplicitHydrogenCount.Value]++;
                }
                for (int k = i + 1; k < som.Count; k++)
                {
                    try
                    {
                        var   result         = cm.DoCrossover(som[i], som[k]);
                        int[] hydrogencount2 = new int[4];
                        foreach (var atom in som[k].Atoms)
                        {
                            hydrogencount2[atom.ImplicitHydrogenCount.Value]++;
                        }
                        Assert.AreEqual(2, result.Count, "Result size must be 2");
                        for (int l = 0; l < 2; l++)
                        {
                            IAtomContainer ac = result[l];
                            Assert.IsTrue(ConnectivityChecker.IsConnected(ac), "Result must be connected");
                            Assert.AreEqual(
                                MolecularFormulaManipulator.GetString(MolecularFormulaManipulator.GetMolecularFormula(ac)),
                                correctFormula,
                                "Molecular formula must be the same as" + "of the input");
                            int[] hydrogencountresult = new int[4];
                            int   hcounttotal         = 0;
                            foreach (var atom in result[l].Atoms)
                            {
                                hydrogencountresult[atom.ImplicitHydrogenCount.Value]++;
                                hcounttotal += atom.ImplicitHydrogenCount.Value;
                            }
                            if (hydrogencount1[0] == hydrogencount2[0])
                            {
                                Assert.AreEqual(
                                    hydrogencount1[0], hydrogencountresult[0],
                                    "Hydrogen count of the result must" + " be same as of input");
                            }
                            if (hydrogencount1[1] == hydrogencount2[1])
                            {
                                Assert.AreEqual(
                                    hydrogencount1[1], hydrogencountresult[1],
                                    "Hydrogen count of the result must" + " be same as of input");
                            }
                            if (hydrogencount1[2] == hydrogencount2[2])
                            {
                                Assert.AreEqual(
                                    hydrogencount1[2], hydrogencountresult[2],
                                    "Hydrogen count of the result must" + " be same as of input");
                            }
                            if (hydrogencount1[3] == hydrogencount2[3])
                            {
                                Assert.AreEqual(
                                    hydrogencount1[3], hydrogencountresult[3],
                                    "Hydrogen count of the result must" + " be same as of input");
                            }
                            Assert.AreEqual(16, hcounttotal);
                        }
                    }
                    catch (CDKException)
                    {
                        errorcount++;
                    }
                }
            }
            Assert.IsTrue(errorcount < 300, "We tolerate up to 300 errors");
        }