コード例 #1
0
ファイル: ModelBuilder3D.cs プロジェクト: roddickchen/NCDK
        /// <summary>
        /// Search and place branches of a chain or ring.
        /// </summary>
        /// <param name="chain">AtomContainer if atoms in an aliphatic chain or ring system</param>
        private void SearchAndPlaceBranches(IAtomContainer molecule, IAtomContainer chain, AtomPlacer3D ap3d,
                                            AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer)
        {
            //Debug.WriteLine("****** SEARCH AND PLACE ****** Chain length: "+chain.Atoms.Count);
            IAtomContainer branchAtoms    = molecule.Builder.NewAtomContainer();
            IAtomContainer connectedAtoms = molecule.Builder.NewAtomContainer();

            for (int i = 0; i < chain.Atoms.Count; i++)
            {
                var atoms = molecule.GetConnectedAtoms(chain.Atoms[i]);
                foreach (var atom in atoms)
                {
                    if (!atom.AtomicNumber.Equals(AtomicNumbers.H) & !atom.IsPlaced & !atom.IsInRing)
                    {
                        connectedAtoms.Add(ap3d.GetPlacedHeavyAtoms(molecule, chain.Atoms[i]));
                        try
                        {
                            SetBranchAtom(molecule, atom, chain.Atoms[i], connectedAtoms, ap3d, atlp3d);
                        }
                        catch (CDKException ex2)
                        {
                            Trace.TraceError($"SearchAndPlaceBranchERROR: Cannot find enough neighbour atoms due to {ex2.ToString()}");
                            throw new CDKException($"SearchAndPlaceBranchERROR: Cannot find enough neighbour atoms: {ex2.Message}", ex2);
                        }
                        branchAtoms.Atoms.Add(atom);
                        connectedAtoms.RemoveAllElements();
                    }
                }
            }//for ac.getAtomCount
            PlaceLinearChains3D(molecule, branchAtoms, ap3d, atlp3d, atomPlacer);
        }
コード例 #2
0
ファイル: ModelBuilder3D.cs プロジェクト: roddickchen/NCDK
        /// <summary>
        /// Layout the molecule, starts with ring systems and than aliphatic chains.
        /// </summary>
        /// <param name="ringSetMolecule">ringSystems of the molecule</param>
        private void LayoutMolecule(IReadOnlyList <IRingSet> ringSetMolecule, IAtomContainer molecule, AtomPlacer3D ap3d,
                                    AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer)
        {
            //Debug.WriteLine("****** LAYOUT MOLECULE MAIN *******");
            IAtomContainer ac            = null;
            int            safetyCounter = 0;
            IAtom          atom          = null;

            //Place rest Chains/Atoms
            do
            {
                safetyCounter++;
                atom = ap3d.GetNextPlacedHeavyAtomWithUnplacedRingNeighbour(molecule);
                if (atom != null)
                {
                    //Debug.WriteLine("layout RingSystem...");
                    var unplacedAtom      = ap3d.GetUnplacedRingHeavyAtom(molecule, atom);
                    var ringSetA          = GetRingSetOfAtom(ringSetMolecule, unplacedAtom);
                    var ringSetAContainer = RingSetManipulator.GetAllInOneContainer(ringSetA);
                    templateHandler.MapTemplates(ringSetAContainer, ringSetAContainer.Atoms.Count);

                    if (CheckAllRingAtomsHasCoordinates(ringSetAContainer))
                    {
                    }
                    else
                    {
                        throw new IOException("RingAtomLayoutError: Not every ring atom is placed! Molecule cannot be layout. Sorry");
                    }

                    Vector3 firstAtomOriginalCoord = unplacedAtom.Point3D.Value;
                    Vector3 centerPlacedMolecule   = ap3d.GeometricCenterAllPlacedAtoms(molecule);

                    SetBranchAtom(molecule, unplacedAtom, atom, ap3d.GetPlacedHeavyAtoms(molecule, atom), ap3d, atlp3d);
                    LayoutRingSystem(firstAtomOriginalCoord, unplacedAtom, ringSetA, centerPlacedMolecule, atom, ap3d);
                    SearchAndPlaceBranches(molecule, ringSetAContainer, ap3d, atlp3d, atomPlacer);
                    //Debug.WriteLine("Ready layout Ring System");
                    ringSetA     = null;
                    unplacedAtom = null;
                }
                else
                {
                    //Debug.WriteLine("layout chains...");
                    SetAtomsToUnVisited(molecule);
                    atom = ap3d.GetNextPlacedHeavyAtomWithUnplacedAliphaticNeighbour(molecule);
                    if (atom != null)
                    {
                        ac = atom.Builder.NewAtomContainer();
                        ac.Atoms.Add(atom);
                        SearchAndPlaceBranches(molecule, ac, ap3d, atlp3d, atomPlacer);
                        ac = null;
                    }
                }
            } while (!ap3d.AllHeavyAtomsPlaced(molecule) || safetyCounter > molecule.Atoms.Count);
        }
コード例 #3
0
        public void RescaleBondLength_IAtom_IAtom_Point3d()
        {
            IAtom atom1 = new Atom("C")
            {
                Point3D        = new Vector3(1, 1, 1),
                CovalentRadius = 0.2
            };
            IAtom atom2 = new Atom("C")
            {
                Point3D        = new Vector3(2, 2, 2),
                CovalentRadius = 0.2
            };
            Vector3 newpoint = new AtomTetrahedralLigandPlacer3D().RescaleBondLength(atom1, atom2, atom2.Point3D.Value);

            Assert.AreEqual(0.4, Vector3.Distance(newpoint, atom1.Point3D.Value), 0.001);
        }
コード例 #4
0
        public void TestGet3DCoordinatesForLigands_IAtom_IAtomContainer_IAtomContainer_IAtom_int_Double_double()
        {
            IAtom atom1 = new Atom("C")
            {
                Point3D = new Vector3(1, 1, 1)
            };
            IAtom          atom2 = new Atom("H");
            IAtom          atom3 = new Atom("H");
            IAtom          atom4 = new Atom("H");
            IAtom          atom5 = new Atom("H");
            IBond          bond1 = new Bond(atom1, atom2);
            IBond          bond2 = new Bond(atom1, atom3);
            IBond          bond3 = new Bond(atom1, atom4);
            IBond          bond4 = new Bond(atom1, atom5);
            IAtomContainer ac    = atom1.Builder.NewAtomContainer();

            ac.Atoms.Add(atom1);
            ac.Atoms.Add(atom2);
            ac.Atoms.Add(atom3);
            ac.Atoms.Add(atom4);
            ac.Atoms.Add(atom5);
            atom1.FormalNeighbourCount = 4;
            atom2.FormalNeighbourCount = 1;
            atom3.FormalNeighbourCount = 1;
            atom4.FormalNeighbourCount = 1;
            atom5.FormalNeighbourCount = 1;
            ac.Bonds.Add(bond1);
            ac.Bonds.Add(bond2);
            ac.Bonds.Add(bond3);
            ac.Bonds.Add(bond4);
            IAtomContainer noCoords   = AtomTetrahedralLigandPlacer3D.GetUnsetAtomsInAtomContainer(atom1, ac);
            IAtomContainer withCoords = AtomTetrahedralLigandPlacer3D.GetPlacedAtomsInAtomContainer(atom1, ac);
            var            placer     = new AtomTetrahedralLigandPlacer3D();

            Vector3[] newPoints = placer.Get3DCoordinatesForLigands(atom1, noCoords, withCoords, null, 4, placer.DefaultBondLengthH, -1);
            for (int j = 0; j < noCoords.Atoms.Count; j++)
            {
                if (newPoints[j] == null)
                {
                    Assert.Fail("No coordinates generated for atom " + j);
                }
                IAtom ligand = noCoords.Atoms[j];
                ligand.Point3D = newPoints[j];
            }
            ModelBuilder3DTest.CheckAverageBondLength(ac);
        }
コード例 #5
0
ファイル: ModelBuilder3D.cs プロジェクト: roddickchen/NCDK
        /// <summary>
        /// Layout all aliphatic chains with ZMatrix.
        /// </summary>
        /// <param name="startAtoms">AtomContainer of possible start atoms for a chain</param>
        private void PlaceLinearChains3D(IAtomContainer molecule, IAtomContainer startAtoms, AtomPlacer3D ap3d,
                                         AtomTetrahedralLigandPlacer3D atlp3d, AtomPlacer atomPlacer)
        {
            //Debug.WriteLine("****** PLACE LINEAR CHAINS ******");
            IAtom          dihPlacedAtom        = null;
            IAtom          thirdPlacedAtom      = null;
            IAtomContainer longestUnplacedChain = molecule.Builder.NewAtomContainer();

            if (startAtoms.Atoms.Count == 0)
            {
                //no branch points ->linear chain
                //Debug.WriteLine("------ LINEAR CHAIN - FINISH ------");
            }
            else
            {
                for (int i = 0; i < startAtoms.Atoms.Count; i++)
                {
                    //Debug.WriteLine("FOUND BRANCHED ALKAN");
                    //Debug.WriteLine("Atom NOT NULL:" + molecule.Atoms.IndexOf(startAtoms.GetAtomAt(i)));
                    thirdPlacedAtom = ap3d.GetPlacedHeavyAtom(molecule, startAtoms.Atoms[i]);
                    dihPlacedAtom   = ap3d.GetPlacedHeavyAtom(molecule, thirdPlacedAtom, startAtoms.Atoms[i]);
                    longestUnplacedChain.Atoms.Add(dihPlacedAtom);
                    longestUnplacedChain.Atoms.Add(thirdPlacedAtom);
                    longestUnplacedChain.Atoms.Add(startAtoms.Atoms[i]);
                    longestUnplacedChain.Add(AtomPlacer.GetLongestUnplacedChain(molecule, startAtoms.Atoms[i]));
                    SetAtomsToUnVisited(molecule);

                    if (longestUnplacedChain.Atoms.Count < 4)
                    {
                        //di,third,sec
                        //Debug.WriteLine("------ Single BRANCH METHYLTYP ------");
                        //break;
                    }
                    else
                    {
                        //Debug.WriteLine("LongestUnchainLength:"+longestUnplacedChain.Atoms.Count);
                        ap3d.PlaceAliphaticHeavyChain(molecule, longestUnplacedChain);
                        ap3d.ZMatrixChainToCartesian(molecule, true);
                        SearchAndPlaceBranches(molecule, longestUnplacedChain, ap3d, atlp3d, atomPlacer);
                    }
                    longestUnplacedChain.RemoveAllElements();
                }//for
            }
            //Debug.WriteLine("****** HANDLE ALIPHATICS END ******");
        }
コード例 #6
0
ファイル: AtomPlacer3D.cs プロジェクト: ch-hristov/NCDK
        /// <summary>
        /// Takes the given Z Matrix coordinates and converts them to cartesian coordinates.
        /// The first Atom end up in the origin, the second on on the x axis, and the third
        /// one in the XY plane. The rest is added by applying the Zmatrix distances, angles
        /// and dihedrals. Assign coordinates directly to the atoms.
        /// </summary>
        /// <param name="molecule">the molecule to be placed in 3D</param>
        /// <param name="flagBranched">marks branched chain</param>
        // @author: egonw,cho
        public virtual void ZMatrixChainToCartesian(IAtomContainer molecule, bool flagBranched)
        {
            Vector3?result = null;

            for (int index = 0; index < distances.Length; index++)
            {
                if (index == 0)
                {
                    result = new Vector3(0d, 0d, 0d);
                }
                else if (index == 1)
                {
                    result = new Vector3(distances[1], 0d, 0d);
                }
                else if (index == 2)
                {
                    result = new Vector3(-Math.Cos((angles[2] / 180) * Math.PI) * distances[2] + distances[1],
                                         Math.Sin((angles[2] / 180) * Math.PI) * distances[2], 0);
                }
                else
                {
                    var cd = molecule.Atoms[thirdAtoms[index]].Point3D.Value
                             - molecule.Atoms[secondAtoms[index]].Point3D.Value;
                    var bc = molecule.Atoms[secondAtoms[index]].Point3D.Value
                             - molecule.Atoms[firstAtoms[index - 3]].Point3D.Value;
                    var n1 = Vector3.Cross(cd, bc);
                    n1 = Vector3.Normalize(n1);

                    Vector3 n2;
                    if (index == 3 && flagBranched)
                    {
                        n2 = AtomTetrahedralLigandPlacer3D.Rotate(n1, bc, DIHEDRAL_BRANCHED_CHAIN);
                    }
                    else
                    {
                        n2 = AtomTetrahedralLigandPlacer3D.Rotate(n1, bc, dihedrals[index]);
                    }
                    n2 = Vector3.Normalize(n2);

                    Vector3 ba = new Vector3();
                    if (index == 3 && flagBranched)
                    {
                        ba = AtomTetrahedralLigandPlacer3D.Rotate(cd, n2, (-angles[index] / 180) * Math.PI);
                        ba = AtomTetrahedralLigandPlacer3D.Rotate(ba, cd, (-angles[index] / 180) * Math.PI);
                    }
                    else
                    {
                        ba = AtomTetrahedralLigandPlacer3D.Rotate(cd, n2, (-angles[index] / 180) * Math.PI);
                    }

                    ba = Vector3.Normalize(ba);

                    Vector3 ban = ba;
                    ban *= distances[index];

                    result = molecule.Atoms[firstAtoms[index - 1]].Point3D.Value + ban;
                }
                IAtom atom = molecule.Atoms[firstAtoms[index]];
                if ((atom.Point3D == null || !atom.IsPlaced) &&
                    !atom.IsInRing && IsHeavyAtom(atom))
                {
                    atom.Point3D  = result;
                    atom.IsPlaced = true;
                }
            }
        }
コード例 #7
0
ファイル: ModelBuilder3D.cs プロジェクト: roddickchen/NCDK
        /// <summary>
        /// Sets a branch atom to a ring or aliphatic chain.
        /// </summary>
        /// <param name="unplacedAtom">The new branchAtom</param>
        /// <param name="atomA">placed atom to which the unplaced atom is connected</param>
        /// <param name="atomNeighbours">placed atomNeighbours of atomA</param>
        private static void SetBranchAtom(IAtomContainer molecule, IAtom unplacedAtom, IAtom atomA, IAtomContainer atomNeighbours,
                                          AtomPlacer3D ap3d, AtomTetrahedralLigandPlacer3D atlp3d)
        {
            //Debug.WriteLine("****** SET Branch Atom ****** >"+molecule.Atoms.IndexOf(unplacedAtom));
            IAtomContainer noCoords = molecule.Builder.NewAtomContainer();

            noCoords.Atoms.Add(unplacedAtom);
            Vector3 centerPlacedMolecule = ap3d.GeometricCenterAllPlacedAtoms(molecule);
            IAtom   atomB = atomNeighbours.Atoms[0];

            string atypeNameA        = atomA.AtomTypeName;
            string atypeNameB        = atomB.AtomTypeName;
            string atypeNameUnplaced = unplacedAtom.AtomTypeName;

            double length = ap3d.GetBondLengthValue(atypeNameA, atypeNameUnplaced);
            double angle  = (ap3d.GetAngleValue(atypeNameB, atypeNameA, atypeNameUnplaced)) * Math.PI / 180;

            // Console.Out.WriteLine("A:"+atomA.Symbol+" "+atomA.AtomTypeName+
            // " B:"+atomB.Symbol+" "+atomB.AtomTypeName
            // +" unplaced Atom:"
            // +unplacedAtom.AtomTypeName+" BL:"+length+" Angle:"+angle
            // +" FormalNeighbour:"
            // +atomA.FormalNeighbourCount+" HYB:"+atomA.getFlag
            // (CDKConstants.HYBRIDIZATION_SP2)
            // +" #Neigbhours:"+atomNeighbours.Atoms.Count);
            IAtom atomC = ap3d.GetPlacedHeavyAtom(molecule, atomB, atomA);

            Vector3[] branchPoints = atlp3d.Get3DCoordinatesForLigands(atomA, noCoords, atomNeighbours, atomC,
                                                                       (atomA.FormalNeighbourCount.Value - atomNeighbours.Atoms.Count), length, angle);
            double distance      = 0;
            int    farthestPoint = 0;

            for (int i = 0; i < branchPoints.Length; i++)
            {
                if (Math.Abs(Vector3.Distance(branchPoints[i], centerPlacedMolecule)) > Math.Abs(distance))
                {
                    distance      = Vector3.Distance(branchPoints[i], centerPlacedMolecule);
                    farthestPoint = i;
                }
            }

            int   stereo       = -1;
            IBond unplacedBond = molecule.GetBond(atomA, unplacedAtom);

            if (atomA.StereoParity != 0 ||
                (unplacedBond.Stereo == BondStereo.Up || unplacedBond.Stereo == BondStereo.Down) &&
                molecule.GetMaximumBondOrder(atomA) == BondOrder.Single)
            {
                if (atomNeighbours.Atoms.Count > 1)
                {
                    stereo = AtomTetrahedralLigandPlacer3D.MakeStereocenter(atomA.Point3D.Value, molecule.GetBond(atomA, unplacedAtom),
                                                                            (atomNeighbours.Atoms[0]).Point3D.Value, (atomNeighbours.Atoms[1]).Point3D.Value,
                                                                            branchPoints);
                }
            }
            if (stereo != -1)
            {
                farthestPoint = stereo;
            }
            unplacedAtom.Point3D  = branchPoints[farthestPoint];
            unplacedAtom.IsPlaced = true;
        }
コード例 #8
0
ファイル: ModelBuilder3D.cs プロジェクト: roddickchen/NCDK
        /// <summary>
        /// Layout the ring system, rotate and translate the template.
        /// </summary>
        /// <param name="originalCoord">coordinates of the placedRingAtom from the template</param>
        /// <param name="placedRingAtom">placedRingAtom</param>
        /// <param name="ringSet">ring system which placedRingAtom is part of</param>
        /// <param name="centerPlacedMolecule">the geometric center of the already placed molecule</param>
        /// <param name="atomB">placed neighbour atom of placedRingAtom</param>
        private static void LayoutRingSystem(Vector3 originalCoord, IAtom placedRingAtom, IRingSet ringSet,
                                             Vector3 centerPlacedMolecule, IAtom atomB, AtomPlacer3D ap3d)
        {
            //Debug.WriteLine("****** Layout ring System ******");Console.Out.WriteLine(">around atom:"+molecule.Atoms.IndexOf(placedRingAtom));
            IAtomContainer ac       = RingSetManipulator.GetAllInOneContainer(ringSet);
            Vector3        newCoord = placedRingAtom.Point3D.Value;
            Vector3        axis     = new Vector3(atomB.Point3D.Value.X - newCoord.X, atomB.Point3D.Value.Y - newCoord.Y, atomB.Point3D.Value.Z - newCoord.Z);

            TranslateStructure(originalCoord, newCoord, ac);
            //Rotate Ringsystem to farthest possible point
            Vector3 startAtomVector    = new Vector3(newCoord.X - atomB.Point3D.Value.X, newCoord.Y - atomB.Point3D.Value.Y, newCoord.Z - atomB.Point3D.Value.Z);
            IAtom   farthestAtom       = ap3d.GetFarthestAtom(placedRingAtom.Point3D.Value, ac);
            Vector3 farthestAtomVector = new Vector3(farthestAtom.Point3D.Value.X - newCoord.X, farthestAtom.Point3D.Value.Y - newCoord.Y, farthestAtom.Point3D.Value.Z - newCoord.Z);
            Vector3 n1 = Vector3.Cross(axis, farthestAtomVector);

            n1 = Vector3.Normalize(n1);
            double  lengthFarthestAtomVector = farthestAtomVector.Length();
            Vector3 farthestVector           = startAtomVector;

            farthestVector  = Vector3.Normalize(farthestVector);
            farthestVector *= startAtomVector.Length() + lengthFarthestAtomVector;
            double  dotProduct = Vector3.Dot(farthestAtomVector, farthestVector);
            double  angle      = Math.Acos(dotProduct / (farthestAtomVector.Length() * farthestVector.Length()));
            Vector3 ringCenter = new Vector3();

            for (int i = 0; i < ac.Atoms.Count; i++)
            {
                if (!(ac.Atoms[i].IsPlaced))
                {
                    ringCenter.X        = (ac.Atoms[i].Point3D).Value.X - newCoord.X;
                    ringCenter.Y        = (ac.Atoms[i].Point3D).Value.Y - newCoord.Y;
                    ringCenter.Z        = (ac.Atoms[i].Point3D).Value.Z - newCoord.Z;
                    ringCenter          = AtomTetrahedralLigandPlacer3D.Rotate(ringCenter, n1, angle);
                    ac.Atoms[i].Point3D =
                        new Vector3(ringCenter.X + newCoord.X, ringCenter.Y + newCoord.Y, ringCenter.Z + newCoord.Z);
                    //ac.GetAtomAt(i).IsPlaced = true;
                }
            }

            //Rotate Ring so that geometric center is max from placed center
            //Debug.WriteLine("Rotate RINGSYSTEM");
            Vector3 pointRingCenter = GeometryUtil.Get3DCenter(ac);
            double  distance        = 0;
            double  rotAngleMax     = 0;

            angle        = 1 / 180 * Math.PI;
            ringCenter   = new Vector3(pointRingCenter.X, pointRingCenter.Y, pointRingCenter.Z);
            ringCenter.X = ringCenter.X - newCoord.X;
            ringCenter.Y = ringCenter.Y - newCoord.Y;
            ringCenter.Z = ringCenter.Z - newCoord.Z;
            for (int i = 1; i < 360; i++)
            {
                ringCenter = AtomTetrahedralLigandPlacer3D.Rotate(ringCenter, axis, angle);
                if (Vector3.Distance(centerPlacedMolecule, new Vector3(ringCenter.X, ringCenter.Y, ringCenter.Z)) > distance)
                {
                    rotAngleMax = i;
                    distance    = Vector3.Distance(centerPlacedMolecule, new Vector3(ringCenter.X, ringCenter.Y, ringCenter.Z));
                }
            }

            //rotate ring around axis with best angle
            rotAngleMax = (rotAngleMax / 180) * Math.PI;
            for (int i = 0; i < ac.Atoms.Count; i++)
            {
                if (!(ac.Atoms[i].IsPlaced))
                {
                    ringCenter.X         = (ac.Atoms[i].Point3D).Value.X;
                    ringCenter.Y         = (ac.Atoms[i].Point3D).Value.Y;
                    ringCenter.Z         = (ac.Atoms[i].Point3D).Value.Z;
                    ringCenter           = AtomTetrahedralLigandPlacer3D.Rotate(ringCenter, axis, rotAngleMax);
                    ac.Atoms[i].Point3D  = new Vector3(ringCenter.X, ringCenter.Y, ringCenter.Z);
                    ac.Atoms[i].IsPlaced = true;
                }
            }
        }
コード例 #9
0
ファイル: ModelBuilder3D.cs プロジェクト: roddickchen/NCDK
        /// <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);
        }