Example #1
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);
        }
Example #2
0
        private static double ReadDouble(CharIter iter)
        {
            int sign = +1;

            if (iter.NextIf('-'))
            {
                sign = -1;
            }
            else if (iter.NextIf('+'))
            {
                sign = +1;
            }
            double intPart;
            double fracPart = 0;
            int    divisor  = 1;

            intPart = (double)ProcessUnsignedInt(iter);
            if (intPart < 0)
            {
                intPart = 0;
            }
            iter.NextIf('.');

            char c;

            while (iter.HasNext() && IsDigit(c = iter.Curr()))
            {
                fracPart *= 10;
                fracPart += c - '0';
                divisor  *= 10;
                iter.Next();
            }

            return(sign * (intPart + (fracPart / divisor)));
        }
Example #3
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);
        }
Example #4
0
        private static int ProcessUnsignedInt(CharIter iter)
        {
            if (!iter.HasNext())
            {
                return(-1);
            }
            char c = iter.Curr();

            if (!IsDigit(c))
            {
                return(-1);
            }
            int res = c - '0';

            iter.Next();
            while (iter.HasNext() && IsDigit(c = iter.Curr()))
            {
                res = res * 10 + c - '0';
                iter.Next();
            }
            return(res);
        }
Example #5
0
 private static bool SkipIntMap(CharIter iter)
 {
     while (iter.HasNext())
     {
         char c = iter.Curr();
         if (Char.IsDigit(c) || c == ',' || c == ':')
         {
             iter.Next();
         }
         else
         {
             return(true);
         }
     }
     // ran of end
     return(false);
 }
Example #6
0
 private static bool SkipIntList(CharIter iter, char sep)
 {
     while (iter.HasNext())
     {
         char c = iter.Curr();
         if (IsDigit(c) || c == sep)
         {
             iter.Next();
         }
         else
         {
             return(true);
         }
     }
     // ran off end
     return(false);
 }
Example #7
0
        /// <summary>
        /// Process atom labels from extended SMILES in a char iter.
        /// </summary>
        /// <param name="iter">char iteration</param>
        /// <param name="dest">destination of labels (atomidx->label)</param>
        /// <returns>parse success/failure</returns>
        private static bool ProcessAtomLabels(CharIter iter, SortedDictionary <int, string> dest)
        {
            int atomIdx = 0;

            while (iter.HasNext())
            {
                // fast forward through empty labels
                while (iter.NextIf(';'))
                {
                    atomIdx++;
                }

                char c = iter.Next();
                if (c == '$')
                {
                    iter.NextIf(','); // optional
                    // end of atom label
                    return(true);
                }
                else
                {
                    iter.pos--; // push back
                    var beg      = iter.pos;
                    var rollback = beg;
                    while (iter.HasNext())
                    {
                        if (iter.pos == beg && iter.Curr() == '_' && iter.Peek() == 'R')
                        {
                            ++beg;
                        }
                        // correct step over of escaped label
                        if (iter.Curr() == '&')
                        {
                            rollback = iter.pos;
                            if (iter.NextIf('&') && iter.NextIf('#') && iter.NextIfDigit())
                            {
                                while (iter.NextIfDigit())
                                {
                                }                              // more digits
                                if (!iter.NextIf(';'))
                                {
                                    iter.pos = rollback;
                                }
                                else
                                {
                                }
                            }
                            else
                            {
                                iter.pos = rollback;
                            }
                        }
                        else if (iter.Curr() == ';')
                        {
                            break;
                        }
                        else if (iter.Curr() == '$')
                        {
                            break;
                        }
                        else
                        {
                            iter.Next();
                        }
                    }
                    dest.Add(atomIdx, Unescape(iter.Substr(beg, iter.pos)));
                    atomIdx++;
                    if (iter.NextIf('$'))
                    {
                        iter.NextIf(','); // optional
                        return(true);
                    }
                    if (!iter.NextIf(';'))
                    {
                        return(false);
                    }
                }
            }
            return(false);
        }
Example #8
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);
        }
Example #9
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);
        }
Example #10
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);
        }