/// <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; }
// # 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(""); }
/// <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); }
/// <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); }
/// 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 } }
/// <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); }
/// <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); }
/// <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 }