Ejemplo n.º 1
0
        public void AtomLabelsEmpty()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|$$|", state));
            Assert.AreEqual(0, state.atomLabels.Count);
        }
Ejemplo n.º 2
0
        public void AtomLabelsTruncated1()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreEqual(-1, CxSmilesParser.ProcessCx("|$;;;Het", state));
            Assert.AreEqual(-1, CxSmilesParser.ProcessCx("|$;;;Het;", state));
        }
Ejemplo n.º 3
0
        public void EscapedAtomLabels()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|$R';;;;;;$|", state));
            Assert.IsTrue(state.atomLabels[0] == "R'");
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Coordinates are written between parenthesis. The z-coord may be omitted '(0,1,),(2,3,)'.
        /// </summary>
        /// <param name="iter">input characters, iterator is progressed by this method</param>
        /// <param name="state">output CXSMILES state</param>
        /// <returns>parse was a success (or not)</returns>
        private static bool ProcessCoords(CharIter iter, CxSmilesState state)
        {
            if (state.atomCoords == null)
            {
                state.atomCoords = new List <double[]>();
            }
            while (iter.HasNext())
            {
                // end of coordinate list
                if (iter.Curr() == ')')
                {
                    iter.Next();
                    iter.NextIf(','); // optional
                    return(true);
                }

                double x = ReadDouble(iter);
                if (!iter.NextIf(','))
                {
                    return(false);
                }
                double y = ReadDouble(iter);
                if (!iter.NextIf(','))
                {
                    return(false);
                }
                double z = ReadDouble(iter);
                iter.NextIf(';');

                state.coordFlag = state.coordFlag || z != 0;
                state.atomCoords.Add(new double[] { x, y, z });
            }
            return(false);
        }
Ejemplo n.º 5
0
        public void HydrogenBondingTruncated()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreEqual(-1, CxSmilesParser.ProcessCx("|H:0.1,2.3", state));
            Assert.AreEqual(-1, CxSmilesParser.ProcessCx("|H:0.1,2.", state));
        }
Ejemplo n.º 6
0
        public void RemoveUnderscore()
        {
            CxSmilesState state = new CxSmilesState();

            CxSmilesParser.ProcessCx("|$;;;_R1;$|", state);
            Assert.AreEqual("R1", state.atomLabels[3]);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Positional variation/multi centre bonding. Describe as a begin atom and one or more end points.
 /// </summary>
 /// <param name="iter">input characters, iterator is progressed by this method</param>
 /// <param name="state">output CXSMILES state</param>
 /// <returns>parse was a success (or not)</returns>
 private static bool ProcessPositionalVariation(CharIter iter, CxSmilesState state)
 {
     if (state.positionVar == null)
     {
         state.positionVar = new SortedDictionary <int, IList <int> >();
     }
     while (iter.HasNext())
     {
         if (IsDigit(iter.Curr()))
         {
             int beg = ProcessUnsignedInt(iter);
             if (!iter.NextIf(':'))
             {
                 return(false);
             }
             var endpoints = new List <int>(6);
             if (!ProcessIntList(iter, DotSeparatorChar, endpoints))
             {
                 return(false);
             }
             iter.NextIf(',');
             state.positionVar.Add(beg, endpoints);
         }
         else
         {
             return(true);
         }
     }
     return(false);
 }
Ejemplo n.º 8
0
        public void EscapedAtomLabels2()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|$;;;&#40;C&#40;R41&#41;&#40;R41&#41;&#41;n;;R41;R41;R41;;_AP1;R41;R41;;_AP1$|", state));
            Assert.IsTrue(state.atomLabels[3] == "(C(R41)(R41))n");
        }
Ejemplo n.º 9
0
        public void AtomLabels()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|$;;;Het;;;;;A$|", state));
            Assert.IsTrue(state.atomLabels.Contains(new KeyValuePair <int, string>(3, "Het")));
            Assert.IsTrue(state.atomLabels.Contains(new KeyValuePair <int, string>(8, "A")));
        }
Ejemplo n.º 10
0
        public void RelativeStereoMolecule()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|r|", state));
            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|r,$_R1$|", state));
            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|$_R1$,r|", state));
        }
Ejemplo n.º 11
0
        public void AtomValues()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|$_AV:;;;5;;;;;8$|", state));
            Assert.IsTrue(state.atomValues.Contains(new KeyValuePair <int, string>(3, "5")));
            Assert.IsTrue(state.atomValues.Contains(new KeyValuePair <int, string>(8, "8")));
        }
Ejemplo n.º 12
0
        public void DataSgroups()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|SgD::cdk&#58;ReactionConditions:Heat&#10;Hv|", state));
            Assert.IsTrue(Compares.DeepContains(
                              state.dataSgroups,
                              new CxSmilesState.DataSgroup(new List <int>(), "cdk:ReactionConditions", "Heat\nHv", "", "", "")));
        }
Ejemplo n.º 13
0
        public void MultiAtomSRU()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|Sg:n:1,2,3:m:ht|", state));
            Assert.IsTrue(Compares.DeepContains(
                              state.sgroups,
                              new CxSmilesState.PolymerSgroup("n", new[] { 1, 2, 3 }, "m", "ht")));
        }
Ejemplo n.º 14
0
        public void FragmentGrouping()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|f:0.1.2.3,4.5.6|", state));
            Assert.IsTrue(Compares.AreDeepEqual(
                              new[] { new[] { 0, 1, 2, 3 }, new[] { 4, 5, 6 } },
                              state.fragGroups));
        }
Ejemplo n.º 15
0
        /// <summary>
        /// CXSMILES radicals.
        /// </summary>
        /// <param name="iter">input characters, iterator is progressed by this method</param>
        /// <param name="state">output CXSMILES state</param>
        /// <returns>parse was a success (or not)</returns>
        private static bool ProcessRadicals(CharIter iter, CxSmilesState state)
        {
            if (state.atomRads == null)
            {
                state.atomRads = new SortedDictionary <int, Radical>();
            }
            CxSmilesState.Radical rad;
            switch (iter.Next())
            {
            case '1':
                rad = Monovalent;
                break;

            case '2':
                rad = Divalent;
                break;

            case '3':
                rad = DivalentSinglet;
                break;

            case '4':
                rad = DivalentTriplet;
                break;

            case '5':
                rad = Trivalent;
                break;

            case '6':
                rad = TrivalentDoublet;
                break;

            case '7':
                rad = TrivalentQuartet;
                break;

            default:
                return(false);
            }
            if (!iter.NextIf(':'))
            {
                return(false);
            }
            var dest = new List <int>(4);

            if (!ProcessIntList(iter, CommaSeparatorChar, dest))
            {
                return(false);
            }
            foreach (var atomidx in dest)
            {
                state.atomRads.Add(atomidx, rad);
            }
            return(true);
        }
Ejemplo n.º 16
0
        public void FragmentGroupingFollowedByAtomLabels()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|f:0.1.2.3,4.5.6,$;;;R$|", state));
            Assert.IsTrue(Compares.AreDeepEqual(
                              new[] { new[] { 0, 1, 2, 3 }, new[] { 4, 5, 6 } },
                              state.fragGroups));
            Assert.IsTrue(state.atomLabels.Contains(new KeyValuePair <int, string>(3, "R")));
        }
Ejemplo n.º 17
0
        public void Multicenter()
        {
            var state = new CxSmilesState {
                positionVar = new SortedDictionary <int, IList <int> >()
            };

            state.positionVar[0] = new[] { 4, 5, 6, 7 };
            state.positionVar[2] = new[] { 4, 6, 5, 7 };
            Assert.AreEqual(" |m:5:0.1.2.3,7:0.1.2.3|", CxSmilesGenerator.Generate(state, SmiFlavors.CxMulticenter, Array.Empty <int>(), new int[] { 7, 6, 5, 4, 3, 2, 1, 0 }));
        }
Ejemplo n.º 18
0
        public void Coords()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|(.0,-1.5,;-1.3,-.75,;-2.6,-1.5,;-3.9,-.75,;-3.9,.75,)|", state));
            Assert.IsTrue(new AprxDoubleArray(0, -1.5, 0).Matches(state.atomCoords[0]));
            Assert.IsTrue(new AprxDoubleArray(-1.3, -.75, 0).Matches(state.atomCoords[1]));
            Assert.IsTrue(new AprxDoubleArray(-2.6, -1.5, 0).Matches(state.atomCoords[2]));
            Assert.IsTrue(new AprxDoubleArray(-3.9, -.75, 0).Matches(state.atomCoords[3]));
            Assert.IsTrue(new AprxDoubleArray(-3.9, .75, 0).Matches(state.atomCoords[4]));
        }
Ejemplo n.º 19
0
        public void PositionalVariationImpliedLayer()
        {
            CxSmilesState state = new CxSmilesState();

            Assert.AreNotEqual(-1, CxSmilesParser.ProcessCx("|m:2:5.6.7.8.9.10,4:5.6.7.8.9|", state));
            Assert.IsTrue(Compares.DeepContains(
                              state.positionVar,
                              new KeyValuePair <int, IList <int> >(2, new[] { 5, 6, 7, 8, 9, 10 })));
            Assert.IsTrue(Compares.DeepContains(
                              state.positionVar,
                              new KeyValuePair <int, IList <int> >(4, new[] { 5, 6, 7, 8, 9 })));
        }
Ejemplo n.º 20
0
        public void Sgroups()
        {
            CxSmilesState state = new CxSmilesState
            {
                sgroups = new List <CxSmilesState.PolymerSgroup>(1)
                {
                    new CxSmilesState.PolymerSgroup("n", new[] { 2, 3 }, "n", "ht"),
                    new CxSmilesState.PolymerSgroup("n", new[] { 5 }, "m", "ht")
                }
            };

            Assert.AreEqual(" |Sg:n:2:m:ht,Sg:n:4,5:n:ht|", CxSmilesGenerator.Generate(state, SmiFlavors.CxPolymer, Array.Empty <int>(), new int[] { 7, 6, 5, 4, 3, 2, 1, 0 }));
        }
Ejemplo n.º 21
0
        public void Radicals()
        {
            CxSmilesState state = new CxSmilesState
            {
                atomRads = new SortedDictionary <int, CxSmilesState.Radical>
                {
                    [2] = CxSmilesState.Radical.Monovalent,
                    [6] = CxSmilesState.Radical.Monovalent,
                    [4] = CxSmilesState.Radical.Divalent
                }
            };

            Assert.AreEqual(" |^1:1,5,^2:3|", CxSmilesGenerator.Generate(state, SmiFlavors.CxSmiles, Array.Empty <int>(), new int[] { 7, 6, 5, 4, 3, 2, 1, 0 }));
        }
Ejemplo n.º 22
0
        public void Coords2d()
        {
            CxSmilesState state = new CxSmilesState
            {
                atomCoords = new List <double[]>
                {
                    new double[] { 0, 1.5, 0 },
                    new double[] { 0, 3, 0 },
                    new double[] { 1.5, 1.5, 0 },
                }
            };

            Assert.AreEqual(" |(1.5,1.5,;,1.5,;,3,)|", CxSmilesGenerator.Generate(state, SmiFlavors.CxCoordinates, Array.Empty <int>(), new int[] { 1, 2, 0 }));
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Parses CXSMILES layer and set attributes for atoms and bonds on the provided reaction.
        /// </summary>
        /// <param name="title">SMILES title field</param>
        /// <param name="rxn">parsed reaction</param>
        private void ParseRxnCXSMILES(string title, IReaction rxn)
        {
            if (title != null && title.StartsWithChar('|'))
            {
                int           pos;
                CxSmilesState cxstate;
                if ((pos = CxSmilesParser.ProcessCx(title, cxstate = new CxSmilesState())) >= 0)
                {
                    // set the correct title
                    rxn.SetProperty(CDKPropertyName.Title, title.Substring(pos));

                    var atomToMol = new Dictionary <IAtom, IAtomContainer>(100);
                    var atoms     = new List <IAtom>();
                    HandleFragmentGrouping(rxn, cxstate);

                    // merge all together
                    foreach (var mol in rxn.Reactants)
                    {
                        foreach (var atom in mol.Atoms)
                        {
                            atoms.Add(atom);
                            atomToMol[atom] = mol;
                        }
                    }
                    foreach (var mol in rxn.Agents)
                    {
                        foreach (var atom in mol.Atoms)
                        {
                            atoms.Add(atom);
                            atomToMol[atom] = mol;
                        }
                    }
                    foreach (var mol in rxn.Products)
                    {
                        foreach (var atom in mol.Atoms)
                        {
                            atoms.Add(atom);
                            atomToMol[atom] = mol;
                        }
                    }

                    AssignCxSmilesInfo(rxn.Builder, rxn, atoms, atomToMol, cxstate);
                }
            }
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Fragment grouping defines disconnected components that should be considered part of a single molecule (i.e.
        /// Salts). Examples include NaH, AlCl3, Cs2CO3, HATU, etc.
        /// </summary>
        /// <param name="iter">input characters, iterator is progressed by this method</param>
        /// <param name="state">output CXSMILES state</param>
        /// <returns>parse was a success (or not)</returns>
        private static bool ProcessFragmentGrouping(CharIter iter, CxSmilesState state)
        {
            if (state.fragGroups == null)
            {
                state.fragGroups = new List <List <int> >();
            }
            var dest = new List <int>();

            while (iter.HasNext())
            {
                dest.Clear();
                if (!ProcessIntList(iter, DotSeparatorChar, dest))
                {
                    return(false);
                }
                iter.NextIf(CommaSeparatorChar);
                if (dest.Count == 0)
                {
                    return(true);
                }
                state.fragGroups.Add(new List <int>(dest));
            }
            return(false);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Parses CXSMILES layer and set attributes for atoms and bonds on the provided molecule.
        /// </summary>
        /// <param name="title">SMILES title field</param>
        /// <param name="mol">molecule</param>
        private void ParseMolCXSMILES(string title, IAtomContainer mol)
        {
            if (title != null && title.StartsWithChar('|'))
            {
                int           pos;
                CxSmilesState cxstate;
                if ((pos = CxSmilesParser.ProcessCx(title, cxstate = new CxSmilesState())) >= 0)
                {
                    // set the correct title
                    mol.Title = title.Substring(pos);

                    var atomToMol = new Dictionary <IAtom, IAtomContainer>(mol.Atoms.Count);
                    var atoms     = new List <IAtom>(mol.Atoms.Count);

                    foreach (var atom in mol.Atoms)
                    {
                        atoms.Add(atom);
                        atomToMol.Add(atom, mol);
                    }

                    AssignCxSmilesInfo(mol.Builder, mol, atoms, atomToMol, cxstate);
                }
            }
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Parse an string possibly containing CXSMILES into an intermediate state
        /// (<see cref="CxSmilesState"/>) representation.
        /// </summary>
        /// <param name="str">input character string (SMILES title field)</param>
        /// <param name="state">output CXSMILES state</param>
        /// <returns>position where CXSMILES ends (below 0 means no CXSMILES)</returns>
        public static int ProcessCx(string str, CxSmilesState state)
        {
            CharIter iter = new CharIter(str);

            if (!iter.NextIf('|'))
            {
                return(-1);
            }

            while (iter.HasNext())
            {
                switch (iter.Next())
                {
                case '$':     // atom labels and values
                              // dest is atom labels by default
                    SortedDictionary <int, string> dest;
                    // check for atom values
                    if (iter.NextIf("_AV:"))
                    {
                        dest = state.atomValues = new SortedDictionary <int, string>();
                    }
                    else
                    {
                        dest = state.atomLabels = new SortedDictionary <int, string>();
                    }
                    if (!ProcessAtomLabels(iter, dest))
                    {
                        return(-1);
                    }
                    break;

                case '(':     // coordinates
                    if (!ProcessCoords(iter, state))
                    {
                        return(-1);
                    }
                    break;

                case 'c':     // cis/trans/unspec ignored
                case 't':
                    // c/t:
                    if (iter.NextIf(':'))
                    {
                        if (!SkipIntList(iter, CommaSeparatorChar))
                        {
                            return(-1);
                        }
                    }
                    // ctu:
                    else if (iter.NextIf("tu:"))
                    {
                        if (!SkipIntList(iter, CommaSeparatorChar))
                        {
                            return(-1);
                        }
                    }
                    break;

                case 'r':     // relative stereochemistry ignored
                    if (iter.NextIf(':'))
                    {
                        if (!SkipIntList(iter, CommaSeparatorChar))
                        {
                            return(-1);
                        }
                    }
                    else
                    {
                        if (!iter.NextIf(',') && iter.Curr() != '|')
                        {
                            return(-1);
                        }
                    }
                    break;

                case 'l':     // lone pairs ignored
                    if (!iter.NextIf("p:"))
                    {
                        return(-1);
                    }
                    if (!SkipIntMap(iter))
                    {
                        return(-1);
                    }
                    break;

                case 'f':     // fragment grouping
                    if (!iter.NextIf(':'))
                    {
                        return(-1);
                    }
                    if (!ProcessFragmentGrouping(iter, state))
                    {
                        return(-1);
                    }
                    break;

                case 'S':     // Sgroup polymers
                    if (iter.NextIf("g:"))
                    {
                        if (!ProcessPolymerSgroups(iter, state))
                        {
                            return(-1);
                        }
                    }
                    else if (iter.NextIf("gD:"))
                    {
                        if (!ProcessDataSgroups(iter, state))
                        {
                            return(-1);
                        }
                    }
                    else
                    {
                        return(-1);
                    }
                    break;

                case 'm':     // positional variation
                    if (!iter.NextIf(':'))
                    {
                        return(-1);
                    }
                    if (!ProcessPositionalVariation(iter, state))
                    {
                        return(-1);
                    }
                    break;

                case '^':     // Radicals
                    if (!ProcessRadicals(iter, state))
                    {
                        return(-1);
                    }
                    break;

                case 'C':
                case 'H':     // coordination and hydrogen bonding ignored
                    if (!iter.NextIf(':'))
                    {
                        return(-1);
                    }
                    while (iter.HasNext() && IsDigit(iter.Curr()))
                    {
                        if (!SkipIntList(iter, DotSeparatorChar))
                        {
                            return(-1);
                        }
                        iter.NextIf(',');
                    }
                    break;

                case '|':     // end of CX
                              // consume optional separators
                    if (!iter.NextIf(' '))
                    {
                        iter.NextIf('\t');
                    }
                    return(iter.pos);

                default:
                    return(-1);
                }
            }

            return(-1);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Polymer Sgroups describe variations of repeating units. Only the atoms and not crossing bonds are written.
        /// </summary>
        /// <param name="iter">input characters, iterator is progressed by this method</param>
        /// <param name="state">output CXSMILES state</param>
        /// <returns>parse was a success (or not)</returns>
        private static bool ProcessPolymerSgroups(CharIter iter, CxSmilesState state)
        {
            if (state.sgroups == null)
            {
                state.sgroups = new List <PolymerSgroup>();
            }
            var beg = iter.pos;

            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            var keyword = iter.Substr(beg, iter.pos);

            if (!iter.NextIf(':'))
            {
                return(false);
            }
            var atomset = new List <int>();

            if (!ProcessIntList(iter, CommaSeparatorChar, atomset))
            {
                return(false);
            }


            string subscript;
            string supscript;

            if (!iter.NextIf(':'))
            {
                return(false);
            }

            // "If the subscript equals the keyword of the Sgroup this field can be empty", ergo
            // if omitted it equals the keyword
            beg = iter.pos;
            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            subscript = Unescape(iter.Substr(beg, iter.pos));
            if (string.IsNullOrEmpty(subscript))
            {
                subscript = keyword;
            }

            // "In the superscript only connectivity and flip information is allowed.", default
            // appears to be "eu" either/unspecified
            if (!iter.NextIf(':'))
            {
                return(false);
            }
            beg = iter.pos;
            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            supscript = Unescape(iter.Substr(beg, iter.pos));
            if (string.IsNullOrEmpty(supscript))
            {
                supscript = "eu";
            }

            if (iter.NextIf(',') || iter.Curr() == '|')
            {
                state.sgroups.Add(new CxSmilesState.PolymerSgroup(keyword, atomset, subscript, supscript));
                return(true);
            }
            // not supported: crossing bond info (difficult to work out from doc) and bracket orientation

            return(false);
        }
Ejemplo n.º 28
0
        private static bool ProcessDataSgroups(CharIter iter, CxSmilesState state)
        {
            if (state.dataSgroups == null)
            {
                state.dataSgroups = new List <DataSgroup>(4);
            }

            var atomset = new List <int>();

            if (!ProcessIntList(iter, CommaSeparatorChar, atomset))
            {
                return(false);
            }

            if (!iter.NextIf(':'))
            {
                return(false);
            }
            var beg = iter.pos;

            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            string field = Unescape(iter.Substr(beg, iter.pos));

            if (!iter.NextIf(':'))
            {
                return(false);
            }
            beg = iter.pos;
            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            string value = Unescape(iter.Substr(beg, iter.pos));

            if (!iter.NextIf(':'))
            {
                state.dataSgroups.Add(new CxSmilesState.DataSgroup(atomset, field, value, "", "", ""));
                return(true);
            }

            beg = iter.pos;
            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            var operator_ = Unescape(iter.Substr(beg, iter.pos));

            if (!iter.NextIf(':'))
            {
                state.dataSgroups.Add(new CxSmilesState.DataSgroup(atomset, field, value, operator_, "", ""));
                return(true);
            }

            beg = iter.pos;
            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            var unit = Unescape(iter.Substr(beg, iter.pos));

            if (!iter.NextIf(':'))
            {
                state.dataSgroups.Add(new CxSmilesState.DataSgroup(atomset, field, value, operator_, unit, ""));
                return(true);
            }

            beg = iter.pos;
            while (iter.HasNext() && !IsSgroupDelim(iter.Curr()))
            {
                iter.Next();
            }
            string tag = Unescape(iter.Substr(beg, iter.pos));

            state.dataSgroups.Add(new CxSmilesState.DataSgroup(atomset, field, value, operator_, unit, tag));

            return(true);
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Transfers the CXSMILES state onto the CDK atom/molecule data-structures.
        /// </summary>
        /// <param name="bldr">chem-object builder</param>
        /// <param name="atoms">atoms parsed from the molecule or reaction. Reaction molecules are list left to right.</param>
        /// <param name="atomToMol">look-up of atoms to molecules when connectivity/sgroups need modification</param>
        /// <param name="cxstate">the CXSMILES state to read from</param>
        private void AssignCxSmilesInfo(IChemObjectBuilder bldr,
                                        IChemObject chemObj,
                                        List <IAtom> atoms,
                                        Dictionary <IAtom, IAtomContainer> atomToMol,
                                        CxSmilesState cxstate)
        {
            // atom-labels - must be done first as we replace atoms
            if (cxstate.atomLabels != null)
            {
                foreach (var e in cxstate.atomLabels)
                {
                    // bounds check
                    if (e.Key >= atoms.Count)
                    {
                        continue;
                    }

                    var old    = atoms[e.Key];
                    var pseudo = bldr.NewPseudoAtom();
                    var val    = e.Value;

                    // specialised label handling
                    if (val.EndsWith("_p", StringComparison.Ordinal)) // pseudo label
                    {
                        val = val.Substring(0, val.Length - 2);
                    }
                    else if (val.StartsWith("_AP", StringComparison.Ordinal)) // attachment point
                    {
                        pseudo.AttachPointNum = ParseIntSafe(val.Substring(3));
                    }

                    pseudo.Label                 = val;
                    pseudo.AtomicNumber          = 0;
                    pseudo.ImplicitHydrogenCount = 0;
                    var mol = atomToMol[old];
                    AtomContainerManipulator.ReplaceAtomByAtom(mol, old, pseudo);
                    atomToMol.Add(pseudo, mol);
                    atoms[e.Key] = pseudo;
                }
            }

            // atom-values - set as comment, mirrors Molfile reading behavior
            if (cxstate.atomValues != null)
            {
                foreach (var e in cxstate.atomValues)
                {
                    atoms[e.Key].SetProperty(CDKPropertyName.Comment, e.Value);
                }
            }

            // atom-coordinates
            if (cxstate.atomCoords != null)
            {
                var numAtoms  = atoms.Count;
                var numCoords = cxstate.atomCoords.Count;
                var lim       = Math.Min(numAtoms, numCoords);
                if (cxstate.coordFlag)
                {
                    for (int i = 0; i < lim; i++)
                    {
                        atoms[i].Point3D = new Vector3(
                            cxstate.atomCoords[i][0],
                            cxstate.atomCoords[i][1],
                            cxstate.atomCoords[i][2]);
                    }
                }
                else
                {
                    for (int i = 0; i < lim; i++)
                    {
                        atoms[i].Point2D = new Vector2(
                            cxstate.atomCoords[i][0],
                            cxstate.atomCoords[i][1]);
                    }
                }
            }

            // atom radicals
            if (cxstate.atomRads != null)
            {
                foreach (var e in cxstate.atomRads)
                {
                    // bounds check
                    if (e.Key >= atoms.Count)
                    {
                        continue;
                    }

                    int count = 0;
                    var aa    = e.Value;
                    switch (e.Value)
                    {
                    case CxSmilesState.Radical.Monovalent:
                        count = 1;
                        break;

                    // no distinction in CDK between singled/triplet
                    case CxSmilesState.Radical.Divalent:
                    case CxSmilesState.Radical.DivalentSinglet:
                    case CxSmilesState.Radical.DivalentTriplet:
                        count = 2;
                        break;

                    // no distinction in CDK between doublet/quartet
                    case CxSmilesState.Radical.Trivalent:
                    case CxSmilesState.Radical.TrivalentDoublet:
                    case CxSmilesState.Radical.TrivalentQuartet:
                        count = 3;
                        break;
                    }
                    var atom = atoms[e.Key];
                    var mol  = atomToMol[atom];
                    while (count-- > 0)
                    {
                        mol.SingleElectrons.Add(bldr.NewSingleElectron(atom));
                    }
                }
            }

            var sgroupMap = new MultiDictionary <IAtomContainer, Sgroup>();

            // positional-variation
            if (cxstate.positionVar != null)
            {
                foreach (var e in cxstate.positionVar)
                {
                    var sgroup = new Sgroup {
                        Type = SgroupType.ExtMulticenter
                    };
                    var beg   = atoms[e.Key];
                    var mol   = atomToMol[beg];
                    var bonds = mol.GetConnectedBonds(beg);
                    if (bonds.Count() == 0)
                    {
                        continue; // bad
                    }
                    sgroup.Add(beg);
                    sgroup.Add(bonds.First());
                    foreach (var endpt in e.Value)
                    {
                        sgroup.Add(atoms[endpt]);
                    }
                    sgroupMap.Add(mol, sgroup);
                }
            }

            // data sgroups
            if (cxstate.dataSgroups != null)
            {
                foreach (var dsgroup in cxstate.dataSgroups)
                {
                    if (dsgroup.Field != null && dsgroup.Field.StartsWith("cdk:", StringComparison.Ordinal))
                    {
                        chemObj.SetProperty(dsgroup.Field, dsgroup.Value);
                    }
                }
            }

            // polymer Sgroups
            if (cxstate.sgroups != null)
            {
                foreach (var psgroup in cxstate.sgroups)
                {
                    var            sgroup  = new Sgroup();
                    var            atomset = new HashSet <IAtom>();
                    IAtomContainer mol     = null;
                    foreach (var idx in psgroup.AtomSet)
                    {
                        if (idx >= atoms.Count)
                        {
                            continue;
                        }
                        var atom = atoms[idx];
                        var amol = atomToMol[atom];

                        if (mol == null)
                        {
                            mol = amol;
                        }
                        else if (amol != mol)
                        {
                            goto C_PolySgroup;
                        }

                        atomset.Add(atom);
                    }

                    if (mol == null)
                    {
                        continue;
                    }

                    foreach (var atom in atomset)
                    {
                        foreach (var bond in mol.GetConnectedBonds(atom))
                        {
                            if (!atomset.Contains(bond.GetOther(atom)))
                            {
                                sgroup.Add(bond);
                            }
                        }
                        sgroup.Add(atom);
                    }

                    sgroup.Subscript = psgroup.Subscript;
                    sgroup.PutValue(SgroupKey.CtabConnectivity, psgroup.Supscript);

                    switch (psgroup.Type)
                    {
                    case "n":
                        sgroup.Type = SgroupType.CtabStructureRepeatUnit;
                        break;

                    case "mon":
                        sgroup.Type = SgroupType.CtabMonomer;
                        break;

                    case "mer":
                        sgroup.Type = SgroupType.CtabMer;
                        break;

                    case "co":
                        sgroup.Type = SgroupType.CtabCopolymer;
                        break;

                    case "xl":
                        sgroup.Type = SgroupType.CtabCrossLink;
                        break;

                    case "mod":
                        sgroup.Type = SgroupType.CtabModified;
                        break;

                    case "mix":
                        sgroup.Type = SgroupType.CtabMixture;
                        break;

                    case "f":
                        sgroup.Type = SgroupType.CtabFormulation;
                        break;

                    case "any":
                        sgroup.Type = SgroupType.CtabAnyPolymer;
                        break;

                    case "gen":
                        sgroup.Type = SgroupType.CtabGeneric;
                        break;

                    case "c":
                        sgroup.Type = SgroupType.CtabComponent;
                        break;

                    case "grf":
                        sgroup.Type = SgroupType.CtabGraft;
                        break;

                    case "alt":
                        sgroup.Type = SgroupType.CtabCopolymer;
                        sgroup.PutValue(SgroupKey.CtabSubType, "ALT");
                        break;

                    case "ran":
                        sgroup.Type = SgroupType.CtabCopolymer;
                        sgroup.PutValue(SgroupKey.CtabSubType, "RAN");
                        break;

                    case "blk":
                        sgroup.Type = SgroupType.CtabCopolymer;
                        sgroup.PutValue(SgroupKey.CtabSubType, "BLO");
                        break;
                    }
                    sgroupMap.Add(mol, sgroup);
C_PolySgroup:
                    ;
                }
            }

            // assign Sgroups
            foreach (var e in sgroupMap)
            {
                e.Key.SetCtabSgroups(new List <Sgroup>(e.Value));
            }
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Handle fragment grouping of a reaction that specifies certain disconnected components
        /// are actually considered a single molecule. Normally used for salts, [Na+].[OH-].
        /// </summary>
        /// <param name="rxn">reaction</param>
        /// <param name="cxstate">state</param>
        private static void HandleFragmentGrouping(IReaction rxn, CxSmilesState cxstate)
        {
            // repartition/merge fragments
            if (cxstate.fragGroups != null)
            {
                const int reactant = 1;
                const int agent    = 2;
                const int product  = 3;

                // note we don't use a list for fragmap as the indexes need to stay consistent
                var fragMap = new SortedDictionary <int, IAtomContainer>();
                var roleMap = new Dictionary <IAtomContainer, int>();

                foreach (var mol in rxn.Reactants)
                {
                    fragMap.Add(fragMap.Count, mol);
                    roleMap.Add(mol, reactant);
                }
                foreach (var mol in rxn.Agents)
                {
                    fragMap.Add(fragMap.Count, mol);
                    roleMap.Add(mol, agent);
                }
                foreach (var mol in rxn.Products)
                {
                    fragMap.Add(fragMap.Count, mol);
                    roleMap.Add(mol, product);
                }

                // check validity of group
                bool invalid = false;
                var  visit   = new HashSet <int>();

                foreach (var grouping in cxstate.fragGroups)
                {
                    var dest = fragMap[grouping[0]];
                    if (dest == null)
                    {
                        continue;
                    }
                    if (visit.Contains(grouping[0]))
                    {
                        invalid = true;
                    }
                    else
                    {
                        visit.Add(grouping[0]);
                    }
                    for (int i = 1; i < grouping.Count; i++)
                    {
                        if (visit.Contains(grouping[i]))
                        {
                            invalid = true;
                        }
                        else
                        {
                            visit.Add(grouping[i]);
                        }
                        var src = fragMap[grouping[i]];
                        if (src != null)
                        {
                            dest.Add(src);
                            roleMap[src] = 0; // no-role
                        }
                    }
                }

                if (!invalid)
                {
                    rxn.Reactants.Clear();
                    rxn.Agents.Clear();
                    rxn.Products.Clear();
                    foreach (var mol in fragMap.Values)
                    {
                        var aa = roleMap[mol];
                        if (aa == reactant)
                        {
                            rxn.Reactants.Add(mol);
                        }
                        else if (aa == product)
                        {
                            rxn.Products.Add(mol);
                        }
                        else if (aa == agent)
                        {
                            rxn.Agents.Add(mol);
                        }
                    }
                }
            }
        }