예제 #1
0
        /// <summary>
        /// The actual writing of the output.
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="CDKException">could not write RGroup query</exception>
        public override void Write(IChemObject obj)
        {
            if (!(obj is IRGroupQuery))
            {
                throw new CDKException("Only IRGroupQuery input is accepted.");
            }
            try
            {
                IRGroupQuery   rGroupQuery = (IRGroupQuery)obj;
                string         now         = DateTime.UtcNow.ToString("MMddyyHHmm", DateTimeFormatInfo.InvariantInfo);
                IAtomContainer rootAtc     = rGroupQuery.RootStructure;

                //Construct header
                var    rootBlock = new StringBuilder();
                string header    = "$MDL  REV  1   " + now + LSEP + "$MOL" + LSEP + "$HDR" + LSEP
                                   + "  Rgroup query file (RGFile)" + LSEP + "  CDK    " + now + "2D" + LSEP + LSEP + "$END HDR"
                                   + LSEP + "$CTAB";
                rootBlock.Append(header).Append(LSEP);

                //Construct the root structure, the scaffold
                string rootCTAB = GetCTAB(rootAtc);
                rootCTAB = rootCTAB.Replace(LSEP + "M  END" + LSEP, "");
                rootBlock.Append(rootCTAB).Append(LSEP);

                //Write the root's LOG lines
                foreach (var rgrpNum in rGroupQuery.RGroupDefinitions.Keys)
                {
                    RGroupList rgList  = rGroupQuery.RGroupDefinitions[rgrpNum];
                    int        restH   = rgList.IsRestH ? 1 : 0;
                    string     logLine = "M  LOG" + MDLV2000Writer.FormatMDLInt(1, 3) + MDLV2000Writer.FormatMDLInt(rgrpNum, 4)
                                         + MDLV2000Writer.FormatMDLInt(rgList.RequiredRGroupNumber, 4)
                                         + MDLV2000Writer.FormatMDLInt(restH, 4) + "   " + rgList.Occurrence;
                    rootBlock.Append(logLine).Append(LSEP);
                }

                //AAL lines are optional, they are needed for R-atoms with multiple bonds to the root
                //for which the order of the attachment points can not be implicitly derived
                //from the order in the atom block. See CT spec for more on that.
                foreach (var rgroupAtom in rGroupQuery.RootAttachmentPoints.Keys)
                {
                    var rApo = rGroupQuery.RootAttachmentPoints[rgroupAtom];
                    if (rApo.Count > 1)
                    {
                        int  prevPos           = -1;
                        int  apoIdx            = 1;
                        bool implicitlyOrdered = true;
                        while (rApo.ContainsKey(apoIdx) && implicitlyOrdered)
                        {
                            IAtom partner = rApo[apoIdx].GetOther(rgroupAtom);
                            for (int atIdx = 0; atIdx < rootAtc.Atoms.Count; atIdx++)
                            {
                                if (rootAtc.Atoms[atIdx].Equals(partner))
                                {
                                    if (atIdx < prevPos)
                                    {
                                        implicitlyOrdered = false;
                                    }
                                    prevPos = atIdx;
                                    break;
                                }
                            }
                            apoIdx++;
                        }
                        if (!implicitlyOrdered)
                        {
                            StringBuilder aalLine = new StringBuilder("M  AAL");
                            for (int atIdx = 0; atIdx < rootAtc.Atoms.Count; atIdx++)
                            {
                                if (rootAtc.Atoms[atIdx].Equals(rgroupAtom))
                                {
                                    aalLine.Append(MDLV2000Writer.FormatMDLInt((atIdx + 1), 4));
                                    aalLine.Append(MDLV2000Writer.FormatMDLInt(rApo.Count, 3));

                                    apoIdx = 1;
                                    while (rApo.ContainsKey(apoIdx))
                                    {
                                        IAtom partner = rApo[apoIdx].GetOther(rgroupAtom);

                                        for (int a = 0; a < rootAtc.Atoms.Count; a++)
                                        {
                                            if (rootAtc.Atoms[a].Equals(partner))
                                            {
                                                aalLine.Append(MDLV2000Writer.FormatMDLInt(a + 1, 4));
                                                aalLine.Append(MDLV2000Writer.FormatMDLInt(apoIdx, 4));
                                            }
                                        }
                                        apoIdx++;
                                    }
                                }
                            }
                            rootBlock.Append(aalLine.ToString()).Append(LSEP);
                        }
                    }
                }

                rootBlock.Append("M  END").Append(LSEP).Append("$END CTAB").Append(LSEP);

                //Construct each R-group block
                var rgpBlock = new StringBuilder();
                foreach (var rgrpNum in rGroupQuery.RGroupDefinitions.Keys)
                {
                    var rgrpList = rGroupQuery.RGroupDefinitions[rgrpNum].RGroups;
                    if (rgrpList != null && rgrpList.Count != 0)
                    {
                        rgpBlock.Append("$RGP").Append(LSEP);;
                        rgpBlock.Append(MDLV2000Writer.FormatMDLInt(rgrpNum, 4)).Append(LSEP);

                        foreach (var rgroup in rgrpList)
                        {
                            //CTAB block
                            rgpBlock.Append("$CTAB").Append(LSEP);
                            string ctab = GetCTAB(rgroup.Group);
                            ctab = ctab.Replace(LSEP + "M  END" + LSEP, "");
                            rgpBlock.Append(ctab).Append(LSEP);

                            //The APO line
                            IAtom firstAttachmentPoint  = rgroup.FirstAttachmentPoint;
                            IAtom secondAttachmentPoint = rgroup.SecondAttachmentPoint;
                            int   apoCount = 0;
                            if (firstAttachmentPoint != null)
                            {
                                var apoLine = new StringBuilder();
                                for (int atIdx = 0; atIdx < rgroup.Group.Atoms.Count; atIdx++)
                                {
                                    if (rgroup.Group.Atoms[atIdx].Equals(firstAttachmentPoint))
                                    {
                                        apoLine.Append(MDLV2000Writer.FormatMDLInt((atIdx + 1), 4));
                                        apoCount++;
                                        if (secondAttachmentPoint != null &&
                                            secondAttachmentPoint.Equals(firstAttachmentPoint))
                                        {
                                            apoLine.Append(MDLV2000Writer.FormatMDLInt(3, 4));
                                        }
                                        else
                                        {
                                            apoLine.Append(MDLV2000Writer.FormatMDLInt(1, 4));
                                        }
                                    }
                                }
                                if (secondAttachmentPoint != null && !secondAttachmentPoint.Equals(firstAttachmentPoint))
                                {
                                    for (int atIdx = 0; atIdx < rgroup.Group.Atoms.Count; atIdx++)
                                    {
                                        if (rgroup.Group.Atoms[atIdx].Equals(secondAttachmentPoint))
                                        {
                                            apoCount++;
                                            apoLine.Append(MDLV2000Writer.FormatMDLInt((atIdx + 1), 4));
                                            apoLine.Append(MDLV2000Writer.FormatMDLInt(2, 4));
                                        }
                                    }
                                }
                                if (apoCount > 0)
                                {
                                    apoLine.Insert(0, "M  APO" + MDLV2000Writer.FormatMDLInt(apoCount, 3));
                                    rgpBlock.Append(apoLine).Append(LSEP);
                                }
                            }

                            rgpBlock.Append("M  END").Append(LSEP);
                            rgpBlock.Append("$END CTAB").Append(LSEP);
                        }
                        rgpBlock.Append("$END RGP").Append(LSEP);
                    }
                }
                rgpBlock.Append("$END MOL").Append(LSEP);

                writer.Write(rootBlock.ToString());
                writer.Write(rgpBlock.ToString());
                writer.Flush();
            }
            catch (IOException e)
            {
                Console.Error.WriteLine(e.StackTrace);
                throw new CDKException("Unexpected exception when writing RGFile" + LSEP + e.Message);
            }
        }