예제 #1
0
        /// <summary>
        /// Applies the MDL valence model to atoms using the explicit valence (bond
        /// order sum) and charge to determine the correct number of implicit
        /// hydrogens. The model is not applied if the explicit valence is less than
        /// 0 - this is the case when a query bond was read for an atom.
        /// </summary>
        /// <param name="atom">the atom to apply the model to</param>
        /// <param name="explicitValence">the explicit valence (bond order sum)</param>
        private static void ApplyMDLValenceModel(IAtom atom, int explicitValence, int unpaired)
        {
            if (atom.Valency != null)
            {
                if (atom.Valency >= explicitValence)
                {
                    atom.ImplicitHydrogenCount = atom.Valency - (explicitValence - unpaired);
                }
                else
                {
                    atom.ImplicitHydrogenCount = 0;
                }
            }
            else
            {
                int element = atom.AtomicNumber;
                int charge  = atom.FormalCharge ?? 0;

                int implicitValence = MDLValence.ImplicitValence(element, charge, explicitValence);
                if (implicitValence < explicitValence)
                {
                    atom.Valency = explicitValence;
                    atom.ImplicitHydrogenCount = 0;
                }
                else
                {
                    atom.Valency = implicitValence;
                    atom.ImplicitHydrogenCount = implicitValence - explicitValence;
                }
            }
        }
예제 #2
0
 public void Nitrogen_anion()
 {
     Assert.AreEqual(2, MDLValence.ImplicitValence(7, -1, 0));
     Assert.AreEqual(2, MDLValence.ImplicitValence(7, -1, 1));
     Assert.AreEqual(2, MDLValence.ImplicitValence(7, -1, 2));
     Assert.AreEqual(3, MDLValence.ImplicitValence(7, -1, 3));
     Assert.AreEqual(4, MDLValence.ImplicitValence(7, -1, 4));
     Assert.AreEqual(5, MDLValence.ImplicitValence(7, -1, 5));
     Assert.AreEqual(6, MDLValence.ImplicitValence(7, -1, 6));
 }
예제 #3
0
        public void Sodium_implicit()
        {
            IAtomContainer container = new AtomContainer();
            IAtom          atom      = new Atom("Na");

            container.Atoms.Add(atom);
            MDLValence.Apply(container);
            Assert.AreEqual(1, atom.Valency);
            Assert.AreEqual(1, atom.ImplicitHydrogenCount);
        }
예제 #4
0
 public void Nitrogen_neutral()
 {
     Assert.AreEqual(3, MDLValence.ImplicitValence(7, 0, 0));
     Assert.AreEqual(3, MDLValence.ImplicitValence(7, 0, 1));
     Assert.AreEqual(3, MDLValence.ImplicitValence(7, 0, 2));
     Assert.AreEqual(3, MDLValence.ImplicitValence(7, 0, 3));
     Assert.AreEqual(5, MDLValence.ImplicitValence(7, 0, 4));
     Assert.AreEqual(5, MDLValence.ImplicitValence(7, 0, 5));
     Assert.AreEqual(6, MDLValence.ImplicitValence(7, 0, 6));
 }
예제 #5
0
        public void Carbon_neutral()
        {
            IAtomContainer container = new AtomContainer();
            IAtom          atom      = new Atom("C");

            container.Atoms.Add(atom);
            MDLValence.Apply(container);
            Assert.AreEqual(4, atom.Valency);
            Assert.AreEqual(4, atom.ImplicitHydrogenCount);
        }
예제 #6
0
        public void Tin_ii()
        {
            IAtomContainer container = new AtomContainer();
            IAtom          atom      = new Atom("Sn");

            atom.Valency = 2;
            container.Atoms.Add(atom);
            MDLValence.Apply(container);
            Assert.AreEqual(2, atom.Valency);
            Assert.AreEqual(2, atom.ImplicitHydrogenCount);
        }
예제 #7
0
        public void Carbon_anion()
        {
            IAtomContainer container = new AtomContainer();
            IAtom          atom      = new Atom("C");

            atom.FormalCharge = +1;
            container.Atoms.Add(atom);
            MDLValence.Apply(container);
            Assert.AreEqual(3, atom.Valency);
            Assert.AreEqual(3, atom.ImplicitHydrogenCount);
        }
예제 #8
0
        public void Tin_iv()
        {
            IAtomContainer container = new AtomContainer();
            IAtom          atom      = new Atom("Sn");

            atom.Valency = 4;
            IAtom hydrogen = new Atom("H");

            container.Atoms.Add(atom);
            container.Atoms.Add(hydrogen);
            container.AddBond(container.Atoms[0], container.Atoms[1], BondOrder.Single);
            MDLValence.Apply(container);
            Assert.AreEqual(4, atom.Valency);
            Assert.AreEqual(3, atom.ImplicitHydrogenCount); // 4 - explicit H
        }
예제 #9
0
        public void Bismuth()
        {
            IAtomContainer container = new AtomContainer();
            IAtom          bi1       = new Atom("Bi");
            IAtom          h2        = new Atom("H");

            bi1.FormalCharge = +2;
            container.Atoms.Add(bi1);
            container.Atoms.Add(h2);
            container.AddBond(container.Atoms[0], container.Atoms[1], BondOrder.Single);
            MDLValence.Apply(container);
            Assert.AreEqual(3, bi1.Valency);
            Assert.AreEqual(1, h2.Valency);
            Assert.AreEqual(2, bi1.ImplicitHydrogenCount);
            Assert.AreEqual(0, h2.ImplicitHydrogenCount);
        }
예제 #10
0
        public void Carbon_cation_DoubleBonded()
        {
            IAtomContainer container = new AtomContainer();
            IAtom          c1        = new Atom("C");
            IAtom          c2        = new Atom("C");

            c1.FormalCharge = -1;
            container.Atoms.Add(c1);
            container.Atoms.Add(c2);
            container.AddBond(container.Atoms[0], container.Atoms[1], BondOrder.Double);
            MDLValence.Apply(container);
            Assert.AreEqual(3, c1.Valency);
            Assert.AreEqual(1, c1.ImplicitHydrogenCount);
            Assert.AreEqual(4, c2.Valency);
            Assert.AreEqual(2, c2.ImplicitHydrogenCount);
        }
예제 #11
0
        /// <summary>
        /// Write the atoms of a molecule. We pass in the order of atoms since for compatibility we
        /// have shifted all hydrogens to the back.
        /// </summary>
        /// <param name="mol">molecule</param>
        /// <param name="atoms">the atoms of a molecule in desired output order</param>
        /// <param name="idxs">index lookup</param>
        /// <param name="atomToStereo">tetrahedral stereo lookup</param>
        /// <exception cref="IOException">low-level IO error</exception>
        /// <exception cref="CDKException">inconsistent state etc</exception>
        private void WriteAtomBlock(IAtomContainer mol, IAtom[] atoms, Dictionary <IChemObject, int> idxs, Dictionary <IAtom, ITetrahedralChirality> atomToStereo)
        {
            if (mol.Atoms.Count == 0)
            {
                return;
            }
            var dim = GetNumberOfDimensions(mol);

            writer.Write("BEGIN ATOM\n");
            int atomIdx = 0;

            foreach (var atom in atoms)
            {
                var elem = NullAsZero(atom.AtomicNumber);
                var chg  = NullAsZero(atom.FormalCharge);
                var mass = NullAsZero(atom.MassNumber);
                var hcnt = NullAsZero(atom.ImplicitHydrogenCount);
                var elec = mol.GetConnectedSingleElectrons(atom).Count();
                int rad  = 0;
                switch (elec)
                {
                case 1:     // 2
                    rad = MDLV2000Writer.SpinMultiplicity.Monovalent.Value;
                    break;

                case 2:     // 1 or 3? Information loss as to which
                    rad = MDLV2000Writer.SpinMultiplicity.DivalentSinglet.Value;
                    break;
                }

                int expVal = 0;
                foreach (var bond in mol.GetConnectedBonds(atom))
                {
                    if (bond.Order == BondOrder.Unset)
                    {
                        throw new CDKException($"Unsupported bond order: {bond.Order}");
                    }
                    expVal += bond.Order.Numeric();
                }

                string symbol = GetSymbol(atom, elem);

                int rnum = -1;
                if (symbol[0] == 'R')
                {
                    var matcher = R_GRP_NUM.Match(symbol);
                    if (matcher.Success)
                    {
                        symbol = "R#";
                        rnum   = int.Parse(matcher.Groups[1].Value, NumberFormatInfo.InvariantInfo);
                    }
                }

                writer.Write(++atomIdx)
                .Write(' ')
                .Write(symbol)
                .Write(' ');
                var p2d = atom.Point2D;
                var p3d = atom.Point3D;
                switch (dim)
                {
                case 0:
                    writer.Write("0 0 0 ");
                    break;

                case 2:
                    if (p2d != null)
                    {
                        writer.Write(p2d.Value.X).WriteDirect(' ')
                        .Write(p2d.Value.Y).WriteDirect(' ')
                        .Write("0 ");
                    }
                    else
                    {
                        writer.Write("0 0 0 ");
                    }
                    break;

                case 3:
                    if (p3d != null)
                    {
                        writer.Write(p3d.Value.X).WriteDirect(' ')
                        .Write(p3d.Value.Y).WriteDirect(' ')
                        .Write(p3d.Value.Z).WriteDirect(' ');
                    }
                    else
                    {
                        writer.Write("0 0 0 ");
                    }
                    break;
                }
                writer.Write(NullAsZero(atom.GetProperty <int>(CDKPropertyName.AtomAtomMapping)));

                if (chg != 0 && chg >= -15 && chg <= 15)
                {
                    writer.Write(" CHG=").Write(chg);
                }
                if (mass != 0)
                {
                    writer.Write(" MASS=").Write(mass);
                }
                if (rad > 0 && rad < 4)
                {
                    writer.Write(" RAD=").Write(rad);
                }
                if (rnum >= 0)
                {
                    writer.Write(" RGROUPS=(1 ").Write(rnum).Write(")");
                }

                // determine if we need to write the valence
                if (MDLValence.ImplicitValence(elem, chg, expVal) - expVal != hcnt)
                {
                    int val = expVal + hcnt;
                    if (val <= 0 || val > 14)
                    {
                        val = -1; // -1 is 0
                    }
                    writer.Write(" VAL=").Write(val);
                }

                if (atomToStereo.TryGetValue(atom, out ITetrahedralChirality stereo))
                {
                    switch (GetLocalParity(idxs, stereo))
                    {
                    case TetrahedralStereo.Clockwise:
                        writer.Write(" CFG=1");
                        break;

                    case TetrahedralStereo.AntiClockwise:
                        writer.Write(" CFG=2");
                        break;

                    default:
                        break;
                    }
                }

                writer.Write('\n');
            }
            writer.Write("END ATOM\n");
        }