Example #1
0
        /// <summary>
        /// Format structure for output to SDFile
        /// </summary>
        /// <param name="molid"></param>

        void FormatSdfileStructure(
            MoleculeMx cs)
        {
            string molFile, cid;

            if (SS.I.RemoveLeadingZerosFromCids)             // normal formatting
            {
                cid = CompoundId.Format(CurrentKey);
            }
            else
            {
                cid = CurrentKey;              // just use internal formatting
            }
            cs      = cs.Convert(Rf.StructureFlags | MoleculeTransformationFlags.RemoveStructureCaption, cid);
            molFile = cs.GetMolfileString();

            if (molFile.IndexOf("\r") < 0)             // add carriage returns to molfile if it doesn't contain them
            {
                molFile = molFile.Replace("\n", "\r\n");
            }

            SdfLine = molFile;

            return;
        }
Example #2
0
        //    # Get list of bits where at least one must be in result fp. Use least popular bits if possible.
        //    if db.mfp_counts:
        //        reqbits = [count['_id'] for count in db.mfp_counts.find({'_id': {'$in': qfp
        //	}
        //}).sort('count', 1).limit(ncommon)]
        //    else:
        //        reqbits = qfp[:ncommon]
        //		results = []
        //    for fp in db.molecules.find({'mfp.bits': {'$in': reqbits}, 'mfp.count': {'$gte': qmin, '$lte': qmax}}):
        //        intersection = len(set(qfp) & set(fp['mfp']['bits']))
        //        pn = fp['mfp']['count']
        //				tanimoto = float(intersection) / (pn + qn - intersection)
        //        if tanimoto >= threshold:
        //            results.append((tanimoto, fp['chembl_id'], fp['smiles']))
        //    return results


        /// <summary>
        /// Test to calculate similarity between pairs of structures (Alt syntax: Call SimSearchMx.Test [cid1] [cid2]
        ///  Tautomers:
        ///  Isotopes:
        ///  Neg Counterion, (Cl-) with 2 quatternary N+ with H attached in main frag:
        ///  Neg Counterion, (I-) with quatternary N+ (no attached H) in main frag:
        ///  Pos Counterion (Li+) with O- in main frag:
        ///  Benzene, cyclohexane:
        ///  StereoIsomers:
        ///  StereoIsomers:
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>

        public static string Test(string args)
        {
            string[] sa   = args.Split(' ');
            string   cid1 = CompoundId.Normalize(sa[0]);
            string   cid2 = CompoundId.Normalize(sa[1]);

            int smiLen = 40;

            MoleculeMx           s1   = MoleculeMx.SelectMoleculeForCid(cid1);
            IAtomContainer       mol  = CdkMol.MolfileToAtomContainer(s1.GetMolfileString());
            UniChemData          ucd1 = UniChemUtil.BuildUniChemData(mol);
            List <FingerprintMx> fps1 = UniChemDataToFingerprintMxList(ucd1);

            MoleculeMx           s2   = MoleculeMx.SelectMoleculeForCid(cid2);
            IAtomContainer       mol2 = CdkMol.MolfileToAtomContainer(s2.GetMolfileString());
            UniChemData          ucd2 = UniChemUtil.BuildUniChemData(mol2);
            List <FingerprintMx> fps2 = UniChemDataToFingerprintMxList(ucd2);

            string fps2Smiles = (sa[0] + " / " + sa[1]).PadRight(smiLen);
            string scores     = "";

            for (int i1 = 0; i1 < fps1.Count; i1++)
            {
                FingerprintMx fp1 = fps1[i1];
                for (int i2 = 0; i2 < fps2.Count; i2++)
                {
                    FingerprintMx fp2 = fps2[i2];

                    if (i1 == 0)                     // build smiles headers of cid2 frags if first cid1 frag
                    {
                        fps2Smiles += "\t" + fp2.CanonSmiles.PadRight(smiLen);
                    }

                    if (i2 == 0)
                    {
                        scores += "\r\n" + fp1.CanonSmiles.PadRight(smiLen);                         // include smiles at start of each line
                    }
                    float simScore = CalculateFingerprintPairSimilarityScore(fp1, fp2);
                    scores += "\t" + string.Format("{0:0.00}", simScore).PadRight(smiLen);
                }
            }

            scores = fps2Smiles + scores;

            FileUtil.WriteAndOpenTextDocument("SimilarityScores", scores);

            return("");
        }
Example #3
0
/// <summary>
/// Build query table for decomposition & add to query
/// </summary>
/// <returns></returns>

        DialogResult ProcessInput()
        {
            Query       q;
            MetaTable   mt;
            MetaColumn  mc;
            QueryTable  qt;
            QueryColumn qc;

            q = QbUtil.Query;
            if (q == null || q.Tables.Count == 0)
            {
                MessageBoxMx.ShowError("No current query.");
                return(DialogResult.None);
            }

            qt = q.GetQueryTableByName("Rgroup_Decomposition");
            bool newTable = false;

            if (qt == null)
            {
                mt       = MetaTableCollection.GetWithException("Rgroup_Decomposition");
                qt       = new QueryTable(mt);
                newTable = true;
            }

            qc = qt.GetQueryColumnByNameWithException("Core");

            MoleculeMx core = new MoleculeMx(MoleculeFormat.Molfile, QueryMolCtl.MolfileString);

            if (core.AtomCount == 0)
            {
                MessageBoxMx.ShowError("A Core structure with R-groups must be defined.");
                return(DialogResult.None);
            }

            qc.MolString       = core.GetMolfileString();       // put core structure into table criteria
            qc.CriteriaDisplay = "Substructure search (SSS)";
            qc.Criteria        = "CORE SSS SQUERY";

            if (!Structure.Checked && !Smiles.Checked && !Formula.Checked &&
                !Weight.Checked && !Index.Checked)
            {
                MessageBoxMx.ShowError("At least one substituent display format must be selected.");
                return(DialogResult.None);
            }

            qc = qt.GetQueryColumnByName("R1_Structure");
            if (ShowCoreStructure.Checked)
            {
                qc.Label            = "R-group, Core\tChime=" + core.GetChimeString();      // reference core in query col header label
                qc.MetaColumn.Width = 25;
            }

            SetSelected(qt, "R1_Structure", Structure.Checked);
            SetSelected(qt, "R1_Smiles", Smiles.Checked);
            SetSelected(qt, "R1_Formula", Formula.Checked);
            SetSelected(qt, "R1_Weight", Weight.Checked);
            SetSelected(qt, "R1_SubstNo", Index.Checked);

            string terminateOption = TerminateOption.Text;

            qc = qt.GetQueryColumnByName("Terminate_Option");
            if (qc != null && Lex.IsDefined(terminateOption))
            {
                qc.Criteria        = qt.MetaTable.Name + " = " + Lex.AddSingleQuotes(terminateOption);
                qc.CriteriaDisplay = "= " + Lex.AddSingleQuotes(terminateOption);
            }

            else
            {
                qc.Criteria = qc.CriteriaDisplay = "";              // not defined
            }
            if (newTable)
            {
                q.AddQueryTable(qt);          // add to query if new
            }
            QbUtil.RenderQuery();             // show it
            UsageDao.LogEvent("RgroupDecomposition");
            return(DialogResult.OK);
        }
Example #4
0
        /// <summary>
        /// Format a chemical structure for Html output
        /// </summary>
        /// <param name="mol"></param>
        /// <param name="destRect"></param>
        /// <param name="width"></param>
        /// <param name="r"></param>
        /// <returns></returns>

        string FormatChemStructureHtml(
            MoleculeMx mol,
            Rectangle destRect,
            int width,
            int r)
        {
            string source, molfil, html, shtml, fname, txt, txt2, str, hdisp, rntxt, html_end;
            int    width2, pixWidth, pixHeight, height, rc, i1;
            bool   useChimeString = false;           // must use molfile format for .Net 4.0 with Draw 4.0

            MolCount++;
            string objId = "Mol" + MolCount;

            //double scaleUp = (SS.I.GraphicsColumnZoom / 100.0) * 1.2; // do graphics scaleup plus a bit
            double scaleUp = 1.2;             // extra scaleup

            pixWidth = (int)(width / 1000.0 * GraphicsMx.LogicalPixelsX * scaleUp);
            height   = (int)(width * .67);
            if (destRect.Height > height)
            {
                height = destRect.Height;
            }
            pixHeight = (int)(height / 1000.0 * GraphicsMx.LogicalPixelsY * scaleUp);

            shtml =             // html for structure
                    "<object id=\"" + objId + "\" " +
                    "codebase=\"<editor>.dll#-1,-1,-1,-1\" " +
                    "height=\"<pixHeight>\" width=\"<pixWidth>\" " +
                    "classid=\"CLSID:46803AAE-C327-4002-8CEC-05036E2FDEF4\"> " +      //
                    "<param name=\"<molStringFormat>\" value=\"<molString>\"> " +
                    "</object>";

            shtml = shtml.Replace("<pixWidth>", pixWidth.ToString());
            shtml = shtml.Replace("<pixHeight>", pixHeight.ToString());
            if (useChimeString)
            {
                shtml = shtml.Replace("<molStringFormat>", "ChimeString");
                shtml = shtml.Replace("<molString>", mol.GetChimeString());
            }

            else
            {
                shtml = shtml.Replace("<molStringFormat>", "MolfileString");
                string mfs = mol.GetMolfileString();
                if (mfs.Contains("\t"))                 // replace any tabs by a space
                {
                    mfs = mfs.Replace("\t", " ");
                }
                shtml = shtml.Replace("<molString>", mfs);
            }

            string script =                                            // set mol parameters
                            "<script language=\"JavaScript\"> " +
                            objId + ".Preferences.WedgeWidth = .3; " + // in .33 inch units
                            objId + ".Preferences.StandardBondLength = 144; " +
                            objId + ".Preferences.ColorAtomsByType = false; " +
                            objId + ".Preferences.HydrogenDisplayMode = 1; " +            // 1= Hetero
                            objId + ".Preferences.ChemLabelFontString = \"Arial, 16\"; "; // make font larger


            // New stero parameters

            script +=
                objId + ".Preferences.StereoAbsColorString = \"Black\"; " +
                objId + ".Preferences.StereoAndColorString = \"Black\"; " +
                objId + ".Preferences.StereoOrColorString = \"Black\"; " +

                objId + ".Preferences.DisplayChiralStereoLabels = 2; " +     // (On = 2, default is IUPAC = 0)

                objId + ".Preferences.DisplayRS = true; " +                  // (default = false)

                objId + ".Preferences.RLabelAtAbsCenter = \"R\"; " +         // (default = "R")
                objId + ".Preferences.RLabelAtAndCenter = \"\"; " +          // (default = "R*")
                objId + ".Preferences.RLabelAtOrCenter = \"\"; " +           // (default = "(R)")

                objId + ".Preferences.SLabelAtAbsCenter = \"S\"; " +         // (default = "S")
                objId + ".Preferences.SLabelAtAndCenter = \"\"; " +          // (default = "S*")
                objId + ".Preferences.SLabelAtOrCenter = \"\"; " +           // (default = "(S)")

                objId + ".Preferences.AbsStereoLabelText = \"\"; " +         // (default = "")
                objId + ".Preferences.AndStereoLabelText = \"\"; " +         // (default = "AND Enantiomer")
                objId + ".Preferences.OrStereoLabelText = \"\"; " +          // (default = "OR Enantiomer")
                objId + ".Preferences.MixedStereoLabelText = \"\"; ";        // (default = "Mixed")

            script += "</script> ";

            shtml += " " + script;

            html     = "E <td>";
            html_end = "";             // clear html to add to end
            string label = mol.Caption;

            if (label != null && label != "")             // include compound number
            {
                txt = label;
                if (txt.IndexOf("</") >= 0)                 // label contains already formatted html
                {
                    txt2 = txt.Replace("</a>", "");
                    if (txt2 != txt)                     // move anchor close after structure to allow structure click
                    {
                        txt      = txt2;
                        html_end = "</a>";
                    }
                    html += txt;
                }

                else                                    // label contains a registry number possibly followed by other text, make regno an anchor
                {
                    txt.Replace("\n", "<br>");          // change any newlines to breaks
                    for (i1 = 0; i1 < txt.Length; i1++) // look for end of regno
                    {
                        if (!Char.IsLetterOrDigit(txt[i1]) && txt[i1] != '-' && txt[i1] != ' ')
                        {
                            break;
                        }
                    }
                    if (i1 < txt.Length)
                    {
                        rntxt = txt.Substring(0, i1);
                        txt   = txt.Substring(i1 + 1);
                    }
                    else
                    {
                        rntxt = txt;
                        txt   = "";
                    }

                    string linkTag = "<a href=\"http://Mobius/command?ShowContextMenu:CompoundIdContextMenu:" + rntxt + "\">";
                    txt =                     // create a link to popup the regno operation menu
                          linkTag + rntxt + "</a>" + txt;

                    shtml = linkTag + shtml + "</a>";                     // also include popup on structure

                    html += txt + "<br>";
                }
            }

            html        += "<center>" + shtml + "</center>" + html_end + "</td>\t";
            Tb.Lines[r] += html;             /* finish up & put in buffer */
            return(html);
        }
Example #5
0
        /// Insert Insight for Excel structure

        public static void SetInsightForExcelMolecule(
            int row,
            int col,
            MoleculeMx mol)
        {
            if (LogCalls)
            {
                DebugLog.Message("ExcelOp SetInsightForExcelMolecule " + row + ", " + col);
            }

            if (StructureInsertCount == 0)             // check that AddIn is loaded
            {
                InsightForExcelAddInLoaded = LoadInsightForExcelAddIn();
                if (!InsightForExcelAddInLoaded)
                {
                    DebugLog.Message("Insight Chemistry AddIn failed to load");
                }
            }

            StructureInsertCount++;

            try
            {
                if (MoleculeMx.IsUndefined(mol))
                {
                    return;
                }

                string molFile = mol.GetMolfileString();
                if (!InsightForExcelAddInLoaded)
                {
                    throw new Exception("Insight Chemistry AddIn failed to load");
                }

                CellSelect(row, col);                 // outputCell
                string errorString  = "";
                bool   returnStatus = false;
                string textFormat   = "Automatic";

                string macroPath = "InsightChemistry.xlam!IxlPutChemistryInCell";       // path to macro (don't use fullPath = XlApp.LibraryPath + @"\" + "InsightChemistry.xlam!IxlPutChemistryInCell")

                string fullPath = XlApp.LibraryPath + @"\" + macroPath;                 // (do not use full path)

                //if (StructureInsertCount == 2) throw new Exception("Test Exception"); // debug

                object ro = XlApp.Run(                 // call Insight macro directly (i.e. no added VBA macro in sheet)
                    Macro: macroPath,
                    Arg1: molFile,
                    Arg2: XlRange,
                    Arg3: errorString,
                    Arg4: returnStatus,
                    Arg5: textFormat);

                ReleaseObject(ro);

                return;
            }

            catch (Exception ex)
            {
                string msg = ex.Message;
                try
                {
                    msg =
                        "Insight for Excel Failed\r\n" +
                        "Molecule: " + StructureInsertCount + ", Atoms: " + mol.AtomCount;
                    XlSheet.Cells[row, col] = msg;
                }
                catch (Exception ex2) { ex2 = ex2; }
                throw new Exception(msg, ex);                 // throw exception so failure gets counted
            }
        }
Example #6
0
        /// <summary>
        /// OK button clicked, process input
        /// </summary>
        /// <returns></returns>

        DialogResult ProcessInput()
        {
            int           rgCount;                              // number of Rgroups
            List <Rgroup> rgList;                               // list of existing Rgroups

            bool[]        rgExists;                             // entry = true if rgroup exists in core
            Rgroup        rg;
            bool          oneD, twoD;                           // matrix dimensionality
            List <string> keys = null;
            Dictionary <string, List <QualifiedNumber> > mElem; // matrix element dictionary

            List <RgroupSubstituent>[] rSubs;                   // substituents seen for each Rgroup
            Query        q, q0, q2;
            QueryTable   qt, qt2;
            QueryColumn  qc, qc2;
            MetaTable    mt, mt2;
            MetaColumn   mc, mc2;
            DataTableMx  dt;
            DataRowMx    dr;
            DialogResult dlgRslt;
            string       tok;
            int          ri, rii, si, qti, qci, bi, bi2;

            // Get core structure & list of R-groups

            MoleculeMx core = new MoleculeMx(MoleculeFormat.Molfile, SQuery.MolfileString);

            if (core.AtomCount == 0)
            {
                MessageBoxMx.ShowError("A Core structure with R-groups must be defined");
                return(DialogResult.None);
            }

            if (!Structure.Checked && !Smiles.Checked && !Formula.Checked &&
                !Weight.Checked && !Index.Checked)
            {
                MessageBoxMx.ShowError("At least one substituent display format must be selected.");
                return(DialogResult.None);
            }

            mt = MetaTableCollection.GetWithException("Rgroup_Decomposition");
            qt = new QueryTable(mt);
            qc = qt.GetQueryColumnByNameWithException("Core");

            qc.MolString       = core.GetMolfileString();       // put core structure into table criteria
            qc.CriteriaDisplay = "Substructure search (SSS)";
            qc.Criteria        = "CORE SSS SQUERY";

            qc = qt.GetQueryColumnByNameWithException("R1_Structure");
            if (ShowCoreStructure.Checked)
            {
                qc.Label            = "R-group, Core\tChime=" + core.GetChimeString();      // reference core in query col header label
                qc.MetaColumn.Width = 25;
            }

            RgroupDecomposition.SetSelected(qt, "R1_Structure", Structure.Checked);             // select for retrieval if checked
            RgroupDecomposition.SetSelected(qt, "R1_Smiles", Smiles.Checked);
            RgroupDecomposition.SetSelected(qt, "R1_Formula", Formula.Checked);
            RgroupDecomposition.SetSelected(qt, "R1_Weight", Weight.Checked);
            RgroupDecomposition.SetSelected(qt, "R1_SubstNo", Index.Checked);

            string terminateOption = "First mapping";             // terminate on first complete match

            qc                 = qt.GetQueryColumnByNameWithException("Terminate_Option");
            qc.Criteria        = qt.MetaTable.Name + " = " + Lex.AddSingleQuotes(terminateOption);
            qc.CriteriaDisplay = "= " + Lex.AddSingleQuotes(terminateOption);

            QueryTable rgdQt = qt;             // keep a ref to it

            if (QbUtil.Query == null || QbUtil.Query.Tables.Count == 0)
            {
                MessageBoxMx.ShowError("No current query.");
                return(DialogResult.None);
            }

            q0 = QbUtil.Query;          // original query this analysis is based on
            q  = q0.Clone();            // make copy of source query we can modify
            q.SingleStepExecution = false;

            qti = 0;
            while (qti < q.Tables.Count)             // deselect query columns that we don't want
            {
                qt = q.Tables[qti];
                if (Lex.Eq(qt.MetaTable.Name, "Rgroup_Decomposition"))
                {                 // remove any rgroup decomp table
                    qti++;
                    continue;
                }

                mt = qt.MetaTable;
                if (mt.MultiPivot ||                                 // check for tables not allowed in underlying query
                    mt.MetaBrokerType == MetaBrokerType.CalcField || // (called ShouldPresearchAndTransform previously)
                    mt.MetaBrokerType == MetaBrokerType.MultiTable ||
                    mt.MetaBrokerType == MetaBrokerType.RgroupDecomp)
                {
                    MessageBoxMx.ShowError("Multipivot/Rgroup table \"" + qt.ActiveLabel +
                                           "\" can't be included in an underlying Rgroup Matrix query");
                    return(DialogResult.None);
                }

                for (qci = 0; qci < qt.QueryColumns.Count; qci++)
                {
                    qc = qt.QueryColumns[qci];
                    if (qc.MetaColumn == null)
                    {
                        continue;
                    }

                    switch (qc.MetaColumn.DataType)
                    {
                    case MetaColumnType.CompoundId:                             // keep only these
                    case MetaColumnType.Integer:
                    case MetaColumnType.Number:
                    case MetaColumnType.QualifiedNo:
                    case MetaColumnType.String:
                        break;

                    default:
                        qc.Selected = false;
                        break;
                    }
                }

                qti++;
            }

            q.AddQueryTable(rgdQt);             // Add Rgroup decom table to end of cloned source query

            Progress.Show("Retrieving data...");
            try
            {
                dlgRslt = ToolHelper.ExecuteQuery(ref q, out keys);
                if (dlgRslt != DialogResult.OK)
                {
                    return(dlgRslt);
                }
            }

            catch (Exception ex)
            {
                MessageBoxMx.ShowError("Error executing query:\r\n" + ex.Message);
                return(DialogResult.None);
            }

            if (keys == null || keys.Count == 0)
            {
                Progress.Hide();
                MessageBoxMx.ShowError("No results were returned by the query.");
                return(DialogResult.None);
            }

// Scan modified query to get list of rgroup indexes that are present

            rgExists = new bool[32];
            rgList   = new List <Rgroup>();

            QueryTable rgQt = q.GetQueryTableByName("Rgroup_Decomposition");

            foreach (QueryColumn qc0 in rgQt.QueryColumns)
            {
                mc = qc0.MetaColumn;
                if (!(mc.Name.StartsWith("R") && mc.Name.EndsWith("_STRUCTURE") && qc0.Selected))
                {
                    continue;                     // skip if not a selected Rgroup structure
                }
                int len = mc.Name.Length - ("R" + "_STRUCTURE").Length;
                tok = mc.Name.Substring(1, len);
                if (!int.TryParse(tok, out ri))
                {
                    continue;
                }
                rgExists[ri - 1] = true;
                rg        = new Rgroup();
                rg.RIndex = ri;
                rg.VoPos  = qc0.VoPosition;
                rgList.Add(rg);
            }

            for (bi = 1; bi < rgList.Count; bi++)
            {             // sort by increasing R index
                rg = rgList[bi];
                for (bi2 = bi - 1; bi2 >= 0; bi2--)
                {
                    if (rg.RIndex >= rgList[bi2].RIndex)
                    {
                        break;
                    }
                    rgList[bi2 + 1] = rgList[bi2];
                }

                rgList[bi2 + 1] = rg;
            }

            rgCount = rgList.Count;

            twoD = TwoD.Checked;
            if (rgCount == 1)
            {
                twoD = false;                           // if only 1 rgroup can't do as 2d
            }
            oneD = !twoD;

// Read data into mElem and rgroup substituents into rSubs.
// Matrix mElem is keyed on [R1Smiles, R2Smiles,... RnSmiles, FieldName] for 1d and
// [R1Smiles, R2Smiles,... FieldName, RnSmiles] for 2d

            QueryManager     qm  = q.QueryManager as QueryManager;
            DataTableManager dtm = qm.DataTableManager;

            dt = qm.DataTable;

            mElem = new Dictionary <string, List <QualifiedNumber> >(); // matrix element dictionary
            rSubs = new List <RgroupSubstituent> [32];                  // list of substituents seen for each Rgroup
            for (rii = 0; rii < rgCount; rii++)                         // alloc substituent list for rgroup
            {
                rSubs[rii] = new List <RgroupSubstituent>();
            }

            int rowCount = 0;

            while (true)
            {             // scan data accumulating rgroup substituents and data values
                dr = dtm.FetchNextDataRow();
                if (dr == null)
                {
                    break;
                }
                rowCount++;

                string cid = dr[dtm.KeyValueVoPos] as string;
                string lastMapCid = "", rgroupKey = "", rgroupKeyLast = "";
                int    mapCount = 0;
                for (rii = 0; rii < rgCount; rii++)                 // for
                {
                    MoleculeMx rSub = dr[rgList[rii].VoPos] as MoleculeMx;
                    if (rSub == null || rSub.AtomCount == 0)
                    {
                        continue;
                    }

                    ri = rgList[rii].RIndex;                     // actual R index in query
                    int subIdx = RgroupSubstituent.Get(rSub, rSubs[rii]);
                    //					if (ri == 1 && subIdx != 0) subIdx = subIdx; // debug
                    if (subIdx < 0)
                    {
                        continue;
                    }
                    string rKey = "R" + ri.ToString() + "_" + (subIdx + 1).ToString();

                    if (oneD || rii < rgCount - 1)
                    {
                        if (rgroupKey != "")
                        {
                            rgroupKey += "\t";
                        }
                        rgroupKey += rKey;
                    }

                    else
                    {
                        rgroupKeyLast = rKey;
                    }
                    lastMapCid = cid;
                    mapCount++;
                }

                if (lastMapCid == cid)                 // add the data if compound has a mapping
                {
                    AccumulateMatrixElements(mElem, q, dr, rgroupKey, rgroupKeyLast, cid);
                }

                if (Progress.IsTimeToUpdate)
                {
                    Progress.Show("Retrieving data: " + StringMx.FormatIntegerWithCommas(rowCount) + " rows...");
                }
            }
            if (rowCount == 0)
            {
                Progress.Hide();
                MessageBoxMx.ShowError("No data rows retrieved");
                return(DialogResult.None);
            }

            if (twoD && (rSubs[rgCount - 1] == null || rSubs[rgCount - 1].Count == 0))
            {             // if 2D be sure we have at least one substituent for the last Rgroup
                Progress.Hide();
                MessageBoxMx.ShowError("No substituents found for R" + rgCount.ToString());
                return(DialogResult.None);
            }

            // Create a MetaTable & DataTable for matrix results

            Progress.Show("Analyzing data...");

            mt = new MetaTable();             // create output table
            MatrixCount++;
            mt.Name           = "RGROUPMATRIX_" + MatrixCount;
            mt.Label          = "R-group Matrix " + MatrixCount;
            mt.MetaBrokerType = MetaBrokerType.RgroupDecomp;

            mc =                       // use sequence for key
                 mt.AddMetaColumn("RgroupMatrixId", "No.", MetaColumnType.Integer, ColumnSelectionEnum.Selected, 3);
            mc.ClickFunction = "None"; // avoid hyperlink on this key
            mc.IsKey         = true;

            int maxLeftR = rgCount;

            if (twoD)
            {
                maxLeftR = rgCount - 1;
            }
            for (ri = 0; ri < maxLeftR; ri++)
            {
                string rStr = "R" + (ri + 1).ToString();
                if (Structure.Checked)
                {
                    mc = mt.AddMetaColumn(rStr + "Str", rStr, MetaColumnType.Structure, ColumnSelectionEnum.Selected, 12);
                    if (ri == 0 && ShowCoreStructure.Checked)                     // include core structure above R1 if requested
                    {
                        string chimeString = MoleculeMx.MolfileStringToSmilesString(SQuery.MolfileString);
                        mc.Label = "R1, Core\tChime=" + chimeString;
                        mc.Width = 25;
                    }
                }
                if (Smiles.Checked)
                {
                    mc = mt.AddMetaColumn(rStr + "Smi", rStr + " Smiles", MetaColumnType.String, ColumnSelectionEnum.Selected, 12);
                }
                if (Formula.Checked)
                {
                    mc = mt.AddMetaColumn(rStr + "Mf", rStr + " Formula", MetaColumnType.String, ColumnSelectionEnum.Selected, 8);
                }
                if (Weight.Checked)
                {
                    mc = mt.AddMetaColumn(rStr + "MW", rStr + " Mol. Wt.", MetaColumnType.Number, ColumnSelectionEnum.Selected, 6, ColumnFormatEnum.Decimal, 2);
                }

                if (Index.Checked)
                {
                    mc        = mt.AddMetaColumn(rStr + "Index", rStr + " Subst. Idx.", MetaColumnType.Number, ColumnSelectionEnum.Selected, 4);
                    mc.Format = ColumnFormatEnum.Decimal;
                }
            }

            mc =             // add column to contain result type
                 mt.AddMetaColumn("ResultType", "Result Type", MetaColumnType.String, ColumnSelectionEnum.Selected, 12);

            if (oneD)             // add just 1 column to contain results
            {
                mc = mt.AddMetaColumn("Results", "Results", MetaColumnType.QualifiedNo, ColumnSelectionEnum.Selected, 12);
                mc.MetaBrokerType = MetaBrokerType.RgroupDecomp;                 // broker to do special col handling for cond formtting
                if (QbUtil.Query.UserObject.Id > 0)
                {
                    mc.DetailsAvailable = true;
                }
            }

            else             // add col for each substituent for last rgroup
            {
                string rStr = "R" + rgCount.ToString();
                for (si = 0; si < rSubs[rgCount - 1].Count; si++)
                {
                    string            cName  = rStr + "_" + (si + 1).ToString();
                    string            cLabel = cName.Replace("_", ".");
                    RgroupSubstituent rgs    = rSubs[ri][si];  // get substituent info
                    if (Structure.Checked)                     // include structure
                    {
                        cLabel += "\tChime=" + rgs.Struct.GetChimeString();
                    }

                    else if (Smiles.Checked)
                    {
                        cLabel += " = " + rgs.Struct.GetSmilesString();
                    }

                    else if (Formula.Checked)
                    {
                        cLabel += " = " + rgs.Struct.MolFormula;
                    }

                    else if (Weight.Checked)
                    {
                        cLabel += " = " + rgs.Struct.MolWeight;
                    }

                    else if (Index.Checked)
                    {
                        cLabel += " = " + (si + 1).ToString();
                    }

                    mc = mt.AddMetaColumn(cName, cLabel, MetaColumnType.QualifiedNo, ColumnSelectionEnum.Selected, 12);
                    mc.MetaBrokerType = MetaBrokerType.RgroupDecomp;
                    if (QbUtil.Query.UserObject.Id > 0)
                    {
                        mc.DetailsAvailable = true;
                    }
                }
            }

            MetaTableCollection.UpdateGlobally(mt); // add as a known metatable

            if (mElem.Count == 0)                   // be sure we have a matrix
            {
                Progress.Hide();
                MessageBoxMx.ShowError("No matrix can be created because insufficient data was found.");
                return(DialogResult.None);
            }

            // Build the DataTable

            Progress.Show("Building data table...");

            q2  = new Query();            // build single-table query to hold matrix
            qt2 = new QueryTable(q2, mt);
            dt  = DataTableManager.BuildDataTable(q2);

            Dictionary <string, List <QualifiedNumber> > .KeyCollection kc = mElem.Keys;
            string[] rgKeys = new string[mElem.Count];
            kc.CopyTo(rgKeys, 0);
            Array.Sort(rgKeys);

            string[] rgKey = null, lastRgKey = null;
            int      rki   = 0;

            for (rki = 0; rki < rgKeys.Length; rki++)
            {
                rgKey = rgKeys[rki].Split('\t');

                int riTop = rgCount + 1;                 // all r substituents & field name on left
                if (twoD)
                {
                    riTop = rgCount;
                }

                for (ri = 0; ri < riTop; ri++)                 // see if any changes in left side substituents or field name
                {
                    if (lastRgKey == null || rgKey[ri] != lastRgKey[ri])
                    {
                        break;
                    }
                }
                if (ri < riTop || oneD)                 // if 2d then new row only if some change before last R
                {
                    dr = dt.NewRow();
                    dt.Rows.Add(dr);
                    dr[dtm.KeyValueVoPos + 1] = new NumberMx(dt.Rows.Count);                     // integer row key
                }

                if (!HideRepeatingSubstituents.Checked)
                {
                    ri = 0;                                                     // start at first if not hiding
                }
                lastRgKey = rgKey;

                for (ri = ri; ri < riTop; ri++)                 // build row with these
                {
                    string rgSub = rgKey[ri];                   // get substituent id or table.column name
                    if (rgSub == "")
                    {
                        continue;
                    }

                    if (ri < riTop - 1)
                    {                     // output substituent and/or smiles
                        string rStr = "R" + (ri + 1).ToString();
                        si = rgSub.IndexOf("_");
                        si = Int32.Parse(rgSub.Substring(si + 1)) - 1;                 // get substituent index
                        RgroupSubstituent rgs = rSubs[ri][si];                         // get substituent info

                        if (Structure.Checked)
                        {
                            qc2 = qt2.GetQueryColumnByName(rStr + "Str");
                            dr[QcToDcName(qc2)] = rgs.Struct;
                        }

                        if (Smiles.Checked)
                        {
                            qc2 = qt2.GetQueryColumnByName(rStr + "Smi");
                            dr[QcToDcName(qc2)] = new StringMx(rgs.Struct.GetSmilesString());
                        }

                        if (Formula.Checked)
                        {
                            qc2 = qt2.GetQueryColumnByName(rStr + "Mf");
                            dr[QcToDcName(qc2)] = new StringMx(rgs.Struct.MolFormula);
                        }

                        if (Weight.Checked)
                        {
                            qc2 = qt2.GetQueryColumnByName(rStr + "Mw");
                            dr[QcToDcName(qc2)] = new NumberMx(rgs.Struct.MolWeight);
                        }

                        if (Index.Checked)
                        {
                            qc2 = qt2.GetQueryColumnByName(rStr + "Index");
                            dr[QcToDcName(qc2)] = new NumberMx(si + 1);
                        }
                    }

                    else                                // output field name
                    {
                        string[] sa = rgSub.Split('.'); // get field name
                        qt = q.GetQueryTableByName(sa[0]);
                        qc = qt.GetQueryColumnByName(sa[1]);
                        string fieldName = qc.ActiveLabel;
                        if (q0.Tables.Count >= 3)                         // qualify by table if 3 or more tables in original query
                        {
                            fieldName = qt.ActiveLabel + " - " + fieldName;
                        }

                        qc2 = qt2.GetQueryColumnByName("ResultType");
                        dr[QcToDcName(qc2)] = new StringMx(fieldName);
                    }
                }

                // Output value

                string cName;
                if (oneD)
                {
                    cName = "Results";
                }
                else
                {
                    cName = rgKey[rgCount];                  // get key for this substituent (e.g. R2_1)
                }
                if (Lex.IsUndefined(cName))
                {
                    continue;                                         // may be no substituent match
                }
                qc2 = qt2.GetQueryColumnByName(cName);
                QualifiedNumber qn = SummarizeData(mElem[rgKeys[rki]]);                 // get summarized value
                dr[QcToDcName(qc2)] = qn;
            }

            ToolHelper.DisplayData(q2, dt, true);

            UsageDao.LogEvent("RgroupMatrix");
            Progress.Hide();
            return(DialogResult.OK);
        }
Example #7
0
        /// <summary>
        /// Handle conversion of Mobius custom data types between the grid and the underlying DataSet
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        void ProcessCustomUnboundColumnDataEvent(object sender, CustomColumnDataEventArgs e)
        {
            MobiusDataType     mdt   = null;
            FormattedFieldInfo ffi   = null;
            bool           formatted = false;
            NumberMx       numberEx;
            StringMx       stringEx;
            ImageMx        imageMx;
            DateTimeMx     dateTimeEx;
            DataRowMx      dr = null;
            BandedGridView mbgv;
            int            nonNullDri;
            string         debugMsg;

            if (DebugMx.False)             // fillValuesImmediately debug test
            {
                e.Value = "XXX";
                return;
            }

            DateTime t0     = DateTime.Now;
            int      callId = ++UnboundCalls;        // get id for this call

            if (sender is BandedGridView)
            {
                mbgv = sender as BandedGridView;
            }

            if (Grid.DataSource == null)
            {
                return;
            }
            CellInfo ci = Grid.GetDataTableCellInfo(e.ListSourceRowIndex, e.Column);

            //if (e.ListSourceRowIndex == 2 && ci.DataRowIndex == 1) e = e; // debug
            //if (ci.Mc.DataType == MetaColumnType.CompoundId && ci.DataRowIndex > 0) ci = ci; // debug
            //DebugLog.Message("CustomUnboundColumnData " + ci.DataRowIndex + ", " + ci.DataColIndex + ", " + ci.DataValue.ToString());
            if (ci.Rfld == null)
            {
                return;
            }

            QueryManager     qm   = Grid.QueryManager;
            ResultsFormatter fmtr = qm.ResultsFormatter;
            ResultsFormat    rf   = qm.ResultsFormat;

            if (e.ListSourceRowIndex == GridControl.NewItemRowHandle || e.ListSourceRowIndex >= Qm.DataTable.Rows.Count)             // new row being created
            {
                if (NewRow == null)
                {
                    NewRow = Qm.DataTable.NewRow();
                }
                dr = NewRow;
            }

            else if (e.ListSourceRowIndex >= 0 && ci.DataRowIndex >= 0)             // row exist in DataTable (i.e. not new row)
            {
                AdjustDataRowToRender(ci);
                if (ci.DataRowIndex >= 0)
                {
                    dr = DataTable.Rows[ci.DataRowIndex];
                    if (ci.DataRowIndex == 0)
                    {
                    }
                }
            }

            else
            {
                if (DebugDetails)
                {
                    ClientLog.Message("Fail 1");
                }
                return;                 // something else, ignore
            }

            // Store edited data for unbound column in DataTable

            if (e.IsSetData)
            {
                SetGridData(e, ci);
                return;
            }

            else if (!e.IsGetData)
            {
                return;                                // just return if not GetData as expected
            }
// Get data from underlying unbound dataset & return in format for grid

            //if (ci.Mc.DataType == MetaColumnType.Structure) ci = ci; // debug
            //if (ci.Mc.DataType == MetaColumnType.String) ci = ci; // debug
            //if (ci.DataValue is StringEx && ((StringEx)ci.DataValue).Value == " ") ci = ci; // debug

            UnboundGets++;

            if (dr == null)
            {
                e.Value = null;
                if (DebugDetails)
                {
                    ClientLog.Message("Fail 2");                               // debug
                }
                return;
            }

            if (Dtm.IsRetrievingDataMessageRow(dr) && ci.Mc != null && !ci.Mc.IsGraphical)
            {
                //if (ci.Mc.IsKey) // show retrieving data message for key field
                e.Value = "Retrieving data...";

                return;
            }

            object fieldValue = dr[ci.DataColIndex];

            if (DebugDetails && fieldValue is MoleculeMx)             // debug
            {
                MoleculeMx     cs      = fieldValue as MoleculeMx;
                MoleculeFormat csType  = cs.PrimaryFormat;
                string         csValue = cs.PrimaryValue;
                int            csLen   = cs.PrimaryValue.Length;
                string         molfile = cs.GetMolfileString();
                molfile = molfile;
            }

            try
            {
                // If already formatted use existing formatting info

                ffi = null;
                if (fieldValue is MobiusDataType)
                {
                    mdt = (MobiusDataType)fieldValue;
                    if (mdt.FormattedBitmap != null)
                    {
                        ffi = new FormattedFieldInfo();
                        ffi.FormattedBitmap = mdt.FormattedBitmap;
                    }

                    else if (mdt.FormattedText != null)
                    {
                        ffi = new FormattedFieldInfo();
                        ffi.FormattedText = mdt.FormattedText;
                    }

                    if (ffi != null)                     // if formatted then copy other format attributes as well
                    {
                        ffi.BackColor = mdt.BackColor;
                        ffi.ForeColor = mdt.ForeColor;
                        ffi.Hyperlink = mdt.Hyperlink;
                    }
                }

                // If not formatted then format

                if (ffi == null)                 // need to format?
                {
// Format non-image field (including structures)

                    if (ci.Mc.DataType != MetaColumnType.Image)                     // format other than image immediately
                    {
                        //if (ci.Mc.DataType == MetaColumnType.Structure)  // debug
                        //{
                        //	DebugLog.Message(fieldValue.ToString());
                        //	UIMisc.Beep();
                        //}

                        ffi = fmtr.FormatField(ci.Rt, ci.TableIndex, ci.Rfld, ci.FieldIndex, dr, e.ListSourceRowIndex, fieldValue, ci.DataRowIndex, false);

                        FormatFieldCalls++;
                        if (ci.Mc.DataType == MetaColumnType.Structure)
                        {
                            FormatStructureFieldCalls++;
                        }

                        StoreFormattingInformationInMdt(ffi, fieldValue, dr, ci, mdt);
                        formatted = true;
                    }

// Image: start asynch call to get image in background as necessary since it is too slow to wait for it here

                    else
                    {
                        if (fieldValue is ImageMx)
                        {
                            imageMx = fieldValue as ImageMx;
                        }

                        else
                        {
                            imageMx = new ImageMx();
                            if (fieldValue != null)
                            {
                                if (fieldValue is MobiusDataType)
                                {
                                    imageMx.DbLink = (fieldValue as MobiusDataType).DbLink;
                                }
                                else
                                {
                                    imageMx.DbLink = fieldValue.ToString();                                  // store field value as dblink
                                }
                            }
                            dr.ItemArrayRef[ci.DataColIndex] = imageMx;                             // store new image object without firing event
                        }

                        mdt = imageMx;                         // copy image object to general  MobiusDataType
                        ffi = new FormattedFieldInfo();

                        if (imageMx.FormattedBitmap != null)                         // already have bitmap?
                        {
                            ffi.FormattedBitmap = imageMx.FormattedBitmap;
                        }

                        else if (imageMx.Value != null)                                                        // have the bitmap, just need to scale it
                        {
                            int fieldWidth   = ci.Rfld.FieldWidth;                                             // current field width in milliinches
                            int desiredWidth = (int)((fieldWidth / 1000.0) * GraphicsMx.LogicalPixelsX * 1.0); // width in pixels

                            imageMx.FormattedBitmap = BitmapUtil.ScaleBitmap(imageMx.Value, desiredWidth);
                            ffi.FormattedBitmap     = imageMx.FormattedBitmap;
                        }

                        else if (imageMx.IsRetrievingValue)                         // already retrieving?
                        {
                            ffi.FormattedBitmap = (Bitmap)RetrievingImageMsg.Image; // put up the processing image
                        }
                        else if (SS.I.AsyncImageRetrieval)                          // start async image retrieval
                        {
                            FormatImageFieldCalls++;
                            GetImageBitmapAsync(ci, dr, e.ListSourceRowIndex, fieldValue, imageMx, callId);
                            ffi.FormattedBitmap = (Bitmap)RetrievingImageMsg.Image;                             // put up the processing image
                        }

                        else                         // do synchronous image retrieval
                        {
                            GetImageBitmap(ci, dr, e.ListSourceRowIndex, fieldValue, imageMx, callId);
                            ffi.FormattedBitmap = imageMx.FormattedBitmap;
                            formatted           = true;
                        }
                    }
                }

                //if (ci.Mc.DataType == MetaColumnType.CompoundId && String.IsNullOrEmpty(fmtdFld.Hyperlink)) ci = ci; // debug
                //if (mdt is CompoundId) mdt = mdt; // debug

                if (e.Column.ColumnEdit is RepositoryItemPictureEdit)
                {
                    if (ffi != null && ffi.FormattedBitmap != null)
                    {
                        e.Value = ffi.FormattedBitmap;
                    }
                    else
                    {
                        e.Value = new Bitmap(1, 1);                              // avoid no-image data message
                    }
                    //ffi.FormattedBitmap.Save(@"c:\download\test.bmp"); // debug
                }

                else
                {
                    e.Value = ffi.FormattedText;                   // non-picture column
                }
                if (ci.DataRowIndex == DataTable.Rows.Count - 1 && // if at end of DataTable && more rows available, request them
                    !Dtm.RowRetrievalComplete)
                {
                    //Progress.Show("Retrieving data..."); // put up progress dialog if not already up

                    //if (WaitForMoreDataStartTime.Equals(DateTime.MinValue)) // say we've started waiting for data
                    //{
                    //  WaitForMoreDataStartTime = DateTime.Now;
                    //  ClientLog.Message("Set WaitForMoreDataStartTime: " + WaitForMoreDataStartTime.ToLongTimeString());
                    //}

                    if (Dtm.RowRetrievalState == RowRetrievalState.Paused)
                    {
                        Dtm.StartRowRetrieval();                         // .ReadNextRowsFromQueryEngine(); // restart retrieval
                    }
                }

                else if (Lex.StartsWith(Progress.GetCaption(), "Retrieving data...") || Lex.IsUndefined(Progress.GetCaption()))
                {                 // hide any "Retrieving data..." message
                    Progress.Hide();
                    //SystemUtil.Beep();
                }

                Grid.LastRowRendered = e.ListSourceRowIndex;

                if (DebugDetails)
                {
                    debugMsg =
                        "Grid.GetData: " + callId + ", e.Row = " + e.ListSourceRowIndex +
                        ", e.Col = " + e.Column.AbsoluteIndex + ", Formatted = " + (formatted ? "T" : "F") + ", Time(ms) = " + TimeOfDay.Delta(t0) +
                        ", ColLabel = " + ci.Qc.ActiveLabel;
                    debugMsg += ", FieldValue = ";
                    if (fieldValue != null)
                    {
                        debugMsg += fieldValue.ToString();
                    }
                    debugMsg += ", e.Value = ";
                    if (e.Value != null)
                    {
                        debugMsg += e.Value.ToString();
                    }
                    else
                    {
                        debugMsg += "null";
                    }
                    ClientLog.Message(debugMsg);
                }

                // TODO: This does a some unnecessary hides which cause flashing of the window frame
                // This happens when we are not at the end of the DataTable but don't know if any additional requests
                // for rendering will occur. May be better to move this to DataTableManger when we detect
                // that we have retrieved a row that is below the level of those displayed in the grid or all rows have been retrieved.
                // Also maybe in MoleculeGridControl.RetrievalMonitorTimer_Tick
            }

            catch (Exception ex)
            {
                if (e.Column.ColumnEdit is RepositoryItemPictureEdit)
                {
                    e.Value = new Bitmap(1, 1);                     // avoid no-image data message
                }
                else
                {
                    e.Value = ex.Message;
                }

                string msg = "ColumnView_CustomUnboundColumnData Exception";
                if (ci.Rfld != null)
                {
                    msg += ",  MetaColumn: " + ci.Rfld.MetaColumn.MetaTable.Name + "." + ci.Rfld.MetaColumn.Name;
                }
                msg += ",  DataColIndex: " + ci.DataColIndex + ",  DataRowIndex: " + ci.DataRowIndex;
                if (fieldValue != null)
                {
                    msg += ",  Value: " + fieldValue.ToString();
                }
                ClientLog.Message(msg);
            }


            //			t0 = TimeOfDay.Milliseconds() - t0;
            //			ClientLog.Message("CustomUnboundColumnData event time: " + t0);
        }
Example #8
0
        /// <summary>
        /// NextRow - Return the next matching row value object
        /// </summary>
        /// <returns></returns>

        public override Object[] NextRow()
        {
            throw new NotImplementedException();
#if false
            string   cid         = "";
            Molecule substituent = null;

            Stopwatch swTotal = Stopwatch.StartNew();
            Stopwatch sw      = Stopwatch.StartNew();

            if (Eqp.SearchKeySubset == null || Eqp.SearchKeySubset.Count == 0)
            {
                return(null);
            }

            // Get the structures for the set of keys

            if (CidToStructureDict == null)
            {
                CidToStructureDict = MoleculeUtil.SelectMoleculesForCidList(Eqp.SearchKeySubset);
                KeyListPos         = -1;
                MapPos             = -1;
                int msTime = (int)sw.ElapsedMilliseconds;
                if (RGroupDecomp.Debug)
                {
                    DebugLog.Message("Select " + Eqp.SearchKeySubset.Count + " structures time(ms): " + msTime);
                }
            }

            // Get the next match

            while (true)
            {
                if (KeyListPos < 0 || MapPos + 1 >= MapCount)
                {                 // go to next structure & set up mapping
                    KeyListPos++;
                    if (KeyListPos >= Eqp.SearchKeySubset.Count)
                    {
                        return(null);
                    }
                    cid = Eqp.SearchKeySubset[KeyListPos];
                    if (!CidToStructureDict.ContainsKey(cid))
                    {
                        continue;
                    }

                    MoleculeMx cs      = CidToStructureDict[cid];
                    string     molFile = cs.GetMolfileString();
                    //string chime = cs.ChimeString; // debug
                    if (RGroupDecomp.Debug)
                    {
                        DebugLog.StopwatchMessage("t1", sw);
                    }

                    if (DebugMx.False)                     // debug
                    {
                        //molFile = FileUtil.ReadFile(@"C:\Downloads\RGroupTarget.mol");
                        string targetSmiles = "CC1Cn2cc(c(= O)c3c2c(c(c(c3)F)Cl)S1)C(= O)O";
                        string targetChime  = "CYAAFQwADfwQ19aXPcZERR45lQkn08$hZNXzeJ2yaAhDnxxJou4Gq9od8VG1ykiO63fQpvM8W4C6MR$O3VaZjQwrGr5weW3y^BeUEezndoIivvAbQN58EEHVMAsdPaF4LIsqsf$OCBUPHI5njBB2LIBy3i2cwbrD8T8kFVBVWkTCfIUFUtblI0G7vYiEL^svUWCT^m6tF18I7ISJUp^7WkuzpT9LrBSJLmMl5hHXog$68Q6YPb0^Xp0ftxmy7FDSF^sWib6^JrUMhrHtLfJ3yVMTm9RIrvvKMRQvKqq4G1Ooze5pdlpSdzp7MFl0K1zx4tdnNFoUO1kRPpyZks61qbBz2tU0L$svvojoU4yUlf$^MFF0nqSfGVW2PKv9TReb$knLXffdAAhqBN310WUfdJDoQBNX1a5L2uj9ybNNRLYpaZN1p6WYp2WI^ntQEVTBaJF1Uu28N4o2xudURpVITTKO7omUtpgLoaoOQHazmZG3k^aHPUOQfE0d27eAbE^uxcQUAB";
                        molFile = CdkMol.Util.MoleculeTofMolfileString(CdkMol.Util.ChimeStringToMolecule(targetChime));
                    }

                    Molecule target = CdkMol.Util.MolfileStringToMolecule(molFile);
                    if (RGroupDecomp.Debug)
                    {
                        DebugLog.StopwatchMessage("t2", sw);
                    }

                    MapCount = RGroupDecomp.ProcessTargetMolecule(target);                     // process & get number of maps
                    if (MapCount > 1)
                    {
                        MapCount = MapCount;                                   // debug, seems to always be 1
                    }
                    MapPos = -1;

                    if (RGroupDecomp.Debug)
                    {
                        DebugLog.StopwatchMessage("t3", sw);
                    }
                }

                // Get the substituent for each RGroup for the next mapping

                MapPos++;                                        // get data for next mapping

                for (int si = 0; si < Substituents.Length; si++) // clear substituents
                {
                    Substituents[si] = null;
                }

                for (int fi = 0; fi < RgTotalCount; fi++)
                {
                    Molecule fragment = RGroupDecomp.GetIthMappingFragment(MapPos, fi);
                    if (fragment == null)
                    {
                        break;                                       // must have reached the end
                    }
                    if (RGroupDecomp.Debug)
                    {
                        DebugLog.StopwatchMessage("t4", sw);
                    }

                    int ri = CdkMol.Util.GetFragmentRGroupAssignment(fragment);

                    if (ri >= 0 && ri < Substituents.Length)
                    {
                        Substituents[ri] = fragment;
                    }
                }

                if (RGroupDecomp.Debug)
                {
                    DebugLog.StopwatchMessage("t5", sw);
                }

                // Fill in the Vo

                object[] vo = new object[Qt.SelectedCount];
                for (int ci = 0; ci < SelectList.Count; ci++)
                {
                    MetaColumn mc   = SelectList[ci];
                    string     name = mc.Name.ToLower();

                    if (mc.IsKey)
                    {
                        vo[ci] = Eqp.SearchKeySubset[KeyListPos];
                    }

                    else if (Lex.Eq(name, "Core"))
                    {
                        vo[ci] = CoreChemicalStructure;
                    }

                    else if (Lex.Eq(name, "Terminate_Option"))
                    {
                        vo[ci] = TerminateOptionString;
                    }

                    else if (Lex.Eq(name, "Map_Number"))
                    {
                        vo[ci] = (MapPos + 1).ToString();
                    }

                    else if (Lex.Eq(name, "Map"))
                    {
                        if (RGroupDecomp.Debug)
                        {
                            DebugLog.StopwatchMessage("t6", sw);
                        }

                        MoleculeMx cs = null;

                        try                         // hilight core molecule
                        {
                            if (StrMatcher == null) // initialize matcher with core structure if not done yet
                            {
                                StrMatcher = new StructureMatcher();
                                string molfile2 = CdkMol.Util.RemoveRGroupAttachmentPointAtoms(CoreChemicalStructure.GetMolfileString());
                                if (RGroupDecomp.Debug)
                                {
                                    DebugLog.StopwatchMessage("t7", sw);
                                }

                                MoleculeMx cs2 = new MoleculeMx(MoleculeFormat.Molfile, molfile2);
                                StrMatcher.SetSSSQueryMolecule(cs2);                                 // set core query used for highlighting
                                if (RGroupDecomp.Debug)
                                {
                                    DebugLog.StopwatchMessage("t8", sw);
                                }
                            }

                            Molecule alignedTarget = RGroupDecomp.GetAlignedTargetForMapping(MapPos);
                            if (RGroupDecomp.Debug)
                            {
                                DebugLog.StopwatchMessage("t9", sw);
                            }

                            string chime = CdkMol.Util.MoleculeToChimeString(alignedTarget);
                            if (RGroupDecomp.Debug)
                            {
                                DebugLog.StopwatchMessage("t10", sw);
                            }

                            cs = new MoleculeMx(MoleculeFormat.Chime, chime);
                            cs = StrMatcher.HighlightMatchingSubstructure(cs);
                        }
                        catch (Exception ex) { ex = ex; }

                        vo[ci] = cs;                         // store value

                        if (RGroupDecomp.Debug)
                        {
                            DebugLog.StopwatchMessage("t11", sw);
                        }
                    }

                    else if (Lex.Eq(name, "Is_Map_Complete"))
                    {
                        vo[ci] = "Yes";                         // always complete for PP
                        //else vo[ci] = "No";
                    }

                    else
                    {                     // must be a substituent
                        if (RGroupDecomp.Debug)
                        {
                            DebugLog.StopwatchMessage("t12", sw);
                        }

                        int ri = name.IndexOf("_");
                        if (ri < 0 || !int.TryParse(name.Substring(1, ri - 1), out ri))
                        {
                            continue;                              // in case of bogus name
                        }
                        substituent = Substituents[ri];

                        if (substituent == null)
                        {
                            vo[ci] = null;                             // no mapping found
                            continue;
                        }

                        if (name.EndsWith("_structure"))
                        {
                            string     chime = CdkMol.Util.MoleculeToChimeString(substituent);
                            MoleculeMx cs    = new MoleculeMx(MoleculeFormat.Chime, chime);
                            vo[ci] = cs;
                        }

                        else if (name.EndsWith("_smiles"))
                        {
                            string smiles = CdkMol.Util.MoleculeToSmilesString(substituent);
                            vo[ci] = smiles;
                        }

                        else if (name.EndsWith("_formula"))
                        {
                            string mf = CdkMol.Util.GetMolFormulaDotDisconnect(substituent);
                            vo[ci] = mf;
                        }

                        else if (name.EndsWith("_weight"))
                        {
                            vo[ci] = CdkMol.Util.GetMolWeight(substituent);
                        }

                        else if (name.EndsWith("_substno"))
                        {
                            vo[ci] = ri;
                        }

                        if (RGroupDecomp.Debug)
                        {
                            DebugLog.StopwatchMessage("t13", sw);
                        }
                    }
                }

                int msTime = (int)sw.ElapsedMilliseconds;
                if (RGroupDecomp.Debug)
                {
                    DebugLog.StopwatchMessage("Total Time for Cid: " + cid, swTotal);
                }

                return(vo);
            }
#endif
        }