static SasMapParms GetParmsFromQueryColumnCriteria( QueryColumn qc) { if (Lex.IsUndefined(qc.Criteria)) { return(new SasMapParms()); } ParsedSingleCriteria psc = ParsedSingleCriteria.Parse(qc); if (Lex.IsUndefined(psc.Value)) { return(new SasMapParms()); } SasMapParms smp = SasMapParms.Deserialize(psc.Value); if (smp != null) { return(smp); } else { return(new SasMapParms()); } }
static void StoreParmsInQueryColumnCriteria( SasMapParms smp, QueryColumn qc) { string parms = smp.Serialize(); qc.Criteria = qc.MetaColumnName + " = " + Lex.AddDoubleQuotesIfNeeded(parms); qc.CriteriaDisplay = "Edit..."; }
/// <summary> /// Edit parameters for existing SasMap query/view /// </summary> /// <param name="sasQc"></param> /// <returns></returns> public DialogResult EditCriteria(QueryColumn sasQc) { SasQc = sasQc; BaseQuery = GetBaseQuery(); Parms = GetParmsFromQueryColumnCriteria(sasQc); DialogResult dr = Edit(); if (dr == DialogResult.OK) { StoreParmsInQueryColumnCriteria(Parms, SasQc); } return(dr); }
/// <summary> /// Adding a new SasMap view to an existing query /// </summary> /// <param name="args"></param> /// <returns></returns> public DialogResult ShowInitialViewSetupDialog( QueryColumn sasQc, Query baseQuery) { MetaTable mt; QueryColumn qc = null; DialogResult dr; AssertMx.IsNotNull(sasQc, "SasQc"); AssertMx.IsNotNull(SasQuery, "SasMapQuery"); SasQc = sasQc; BaseQuery = baseQuery; Parms = GetParmsFromQueryColumnCriteria(SasQc); qc = BaseQuery?.GetFirstKeyColumn(); if (qc == null) { qc = QueryTable.GetDefaultRootQueryTable()?.KeyQueryColumn; } qc = qc.Clone(); Parms.KeyCriteriaQc = qc; // assign QC with undefined criteria QueryManager refQm = (baseQuery.QueryManager as QueryManager); List <string> resultsKeys = refQm?.DataTableManager?.ResultsKeys; if (resultsKeys != null && resultsKeys.Count > 0) { string listText = Csv.JoinCsvString(resultsKeys); qc.CriteriaDisplay = CidList.FormatAbbreviatedCidListForDisplay(qc, listText); qc.Criteria = qc.MetaColumn.Name + " IN (" + listText + ")"; } Parms.EndpointMc = BaseQuery?.GetFirstResultColumnByPriority(true)?.MetaColumn; // pick the highest priority result column as the default endpoint dr = Edit(); if (dr == DialogResult.OK) { StoreParmsInQueryColumnCriteria(Parms, SasQc); } return(dr); }
/// <summary> /// Tools menu item click /// Create a standalone SasMap analysis based on the current query and then run it /// </summary> /// <param name="args"></param> /// <returns></returns> public string Run( string args) { QueryTable qt; MetaTable mt; QueryColumn qc; int qid = SS.I.ServicesIniFile.ReadInt("SasMapToolModelQuery", 888070); if (qid < 0) { throw new Exception("SasMapToolModelQuery not defined"); } Query q = QbUtil.ReadQuery(qid); if (q == null) { throw new Exception("Failed to read SasMapToolModelQuery: " + qid); } q.UserObject = new UserObject(UserObjectType.Query); // treat this as a new query QueryTable sasQt = q.GetQueryTableByNameWithException(SasMapParms.MetaTableName); SasQc = sasQt.GetQueryColumnByNameWithException(SasMapParms.ParametersMetaColumnName); BaseQuery = GetBaseQuery(); if (BaseQuery == null || BaseQuery.Tables.Count == 0) { MessageBoxMx.ShowError("The current query must contain one or more data tables before a SasMap can be defined on the query"); return(""); } Parms = LastParms; qc = BaseQuery?.GetFirstKeyColumn(); qc = qc.Clone(); qc.CopyCriteriaFromQueryKeyCriteria(BaseQuery); Parms.KeyCriteriaQc = qc; Parms.EndpointMc = BaseQuery?.GetFirstResultColumnByPriority(true)?.MetaColumn; // pick the highest priority result column as the default endpoint QbUtil.SetMode(QueryMode.Build); // be sure in build mode DialogResult dr = Edit(); if (dr != DialogResult.OK) { return(""); } StoreParmsInQueryColumnCriteria(Parms, SasQc); // Add as a new query and run it AnalysisCount++; q.Name = "Structure-Activity Similarity Analysis " + AnalysisCount; q.SingleStepExecution = true; // Add the query to the QueryBuilder and run it DelayedCallback.Schedule( // add and run the query after exiting this dialog delegate(object state) { QbUtil.AddQuery(q); QbUtil.SetCurrentQueryInstance(q); // set to new query QbUtil.RenderQuery(); QueryExec.RunQuery(q, SS.I.DefaultQueryDest); }); Progress.Hide(); return(""); }
/// <summary> /// Execute query /// </summary> /// <param name="eqp"></param> public override void ExecuteQuery( ExecuteQueryParms eqp) { MetaTable mt; MetaColumn mc; Query q; QueryTable qt; QueryColumn qc; ResultsPage rp; ResultsViewProps view; CompoundStructureActivityData cd1, cd2; bool smallerIsbetter; double r1, r2, r3, r4; int di, di2, pdi, pdi2, i3; string tok; qt = eqp.QueryTable; qc = qt.GetQueryColumnByNameWithException(SasMapParms.ParametersMetaColumnName); AssertMx.IsDefined(qc.Criteria, qc.Label + " criteria not defined"); if (Lex.Eq(qc.Criteria, LastCriteriaString)) // if same criteria as last time then use existing data { VoListPos = -1; // init list position return; } VoList = new List<object[]>(); VoListPos = -1; // init list position LastCriteriaString = qc.Criteria; ParsedSingleCriteria psc = ParsedSingleCriteria.Parse(qc); SMP = SasMapParms.Deserialize(psc.Value); mc = SMP.EndpointMc; smallerIsbetter = mc.MultiPoint; List<CompoundStructureActivityData> ds1 = ReadData(SMP); // read in the data to analyze if (ds1 == null || ds1.Count == 0) return; // throw new QueryException("No data retrieved"); List<CompoundStructureActivityData> ds2 = ds1; // just one set for now // Calculate difference or ratio coefficents for each pair List<PairData> pd = new List<PairData>(); int minCoef = -1; // index of minimum coefficent selected so far double molFactor = AssayAttributes.GetMolarConcFactor(SMP.EndpointMc); for (di = 0; di < ds1.Count; di++) { // process all compounds in 1st set // if (ds1[di].Nearest == 0) continue; // any data? if (ds2 == ds1) di2 = di + 1; // only do lower rt diagonal if one dataset else di2 = 0; // must do all compares, check for dups later for ( /* start at di2 */; di2 < ds2.Count; di2++) { // if (ds2[di2].Nearest == 0) continue; // any data? if (ds1[di].Cid == ds2[di2].Cid) continue; // avoid self compare double sim = // similarity CalculateSimilarity(ds1[di], ds2[di2]); //if (sim==1.0 && !stereo) // eliminate stereo pairs if requested // continue; // a more careful check may be needed if (sim < SMP.MinimumSimilarity) continue; // below cutoff value? double denom = 1 - sim; // denominator is 1 - sim if (denom == 0) denom = .00000000001f; // avoid divide by zero double actChange = 0; if (smallerIsbetter && ds1[di].Activity < ds2[di2].Activity) { cd1 = ds1[di]; cd2 = ds2[di2]; } else { cd1 = ds2[di2]; cd2 = ds1[di]; } double a1 = cd1.Activity; double a2 = cd2.Activity; if (a1 == NullValue.NullNumber || a2 == NullValue.NullNumber) actChange = 0; else switch (SMP.ActDiffCalcType) { case ActDiffCalcType.SimpleDifference: // activity difference { actChange = a1 - a2; break; } case ActDiffCalcType.NegativeLog: { actChange = -Math.Log10(a1) - -Math.Log10(a2); break; } case ActDiffCalcType.MolarNegativeLog: { actChange = (-Math.Log10(a1 * molFactor)) - (-Math.Log10(a2 * molFactor)); break; } case ActDiffCalcType.Ratio: // activity ratio { r1 = a1; if (r1 == 0) r1 = .00000000001f; r2 = a2; if (r2 == 0) r2 = .00000000001f; r3 = r1 / r2; r4 = r2 / r1; actChange = r3; if (SMP.UseAbsoluteValue && r4 > r3) // take the max value actChange = r4; break; } case ActDiffCalcType.Advanced: { throw new InvalidOperationException("SarMapCalcType.Advanced"); } default: throw new InvalidOperationException("SarMapCalcType: " + (int)SMP.ActDiffCalcType); } if (SMP.UseAbsoluteValue && SMP.ActDiffCalcType != ActDiffCalcType.Ratio) actChange = Math.Abs(actChange); double coef = actChange / denom; if (pd.Count < SMP.MaxPairCount) // just add this pair to end { pdi = pd.Count; pd.Add(new PairData()); } else { // see if this value is greater than anything in list if (minCoef < 0) { // find element with minimum coef minCoef = 0; for (i3 = 1; i3 < pd.Count; i3++) { if (pd[i3].Coef < pd[minCoef].Coef) minCoef = i3; } } if (coef <= pd[minCoef].Coef) continue; // if this one better? //if (ds1 != ds2) //{ // be sure not a duplicate of what we have in list // for (i3 = 0; i3 < pd.Count; i3++) // { // check for pair in list already // if ((di == pd[i3].CD1 && di2 == pd[i3].CD2) || // (di == pd[i3].CD2 && di2 == pd[i3].CD1)) break; // } // if (i3 < pd.Count) continue; // continue to next pair if found //} pdi = minCoef; // replace this item minCoef = -1; // reset to get new minimum next time } // Save data for the pair pd[pdi].CD1 = cd1; pd[pdi].CD2 = cd2; pd[pdi].Sim = sim; pd[pdi].ActChange = actChange; pd[pdi].Coef = coef; } } // Build the list of pair Vos int voLen = qt.SetSimpleVoPositions(); PairData pdItem; for (pdi = 1; pdi < pd.Count; pdi++) // sort from max to min coef value { pdItem = pd[pdi]; for (pdi2 = pdi - 1; pdi2 >= 0; pdi2--) { if (pdItem.Coef < pd[pdi2].Coef) break; pd[pdi2 + 1] = pd[pdi2]; } pd[pdi2 + 1] = pdItem; } for (pdi = 0; pdi < pd.Count; pdi++) { pdItem = pd[pdi]; cd1 = pdItem.CD1; cd2 = pdItem.CD2; object[] vo = new object[voLen]; VoArray.SetVo(qt, "PAIR_ID", vo, new NumberMx(pdi + 1)); VoArray.SetVo(qt, "COMPOUND1", vo, new StringMx(cd1.Cid)); VoArray.SetVo(qt, "STRUCTURE1", vo, cd1.Structure); VoArray.SetVo(qt, "ACTIVITY1", vo, new NumberMx(cd1.Activity)); VoArray.SetVo(qt, "COMPOUND2", vo, new StringMx(cd2.Cid)); VoArray.SetVo(qt, "STRUCTURE2", vo, cd2.Structure); VoArray.SetVo(qt, "ACTIVITY2", vo, new NumberMx(cd2.Activity)); VoArray.SetVo(qt, "SIMILARITY", vo, new NumberMx(pdItem.Sim)); VoArray.SetVo(qt, "ACTIVITY_DIFF", vo, new NumberMx(pdItem.ActChange)); VoArray.SetVo(qt, "ACT_SIM_COEF", vo, new NumberMx(pdItem.Coef)); VoList.Add(vo); } VoListPos = -1; // init list position return; }
/// <summary> /// Read input data from database /// </summary> /// <param name="smp"> /// <returns></returns> List<CompoundStructureActivityData> ReadData( SasMapParms smp) { MetaColumn activityMc = smp.EndpointMc; QueryColumn keyCriteriaQc = smp.KeyCriteriaQc; AssertMx.IsNotNull(activityMc, "mc"); AssertMx.IsNotNull(keyCriteriaQc, "keyCriteriaQc"); MetaTable mt, mt2; MetaColumn mc2 = null; Query q = new Query(); mt = activityMc.MetaTable; QueryTable qt = new QueryTable(mt); if (mt.SummarizedExists && !mt.UseSummarizedData) { // retrieve summarized data if exists mt2 = MetaTableCollection.Get(mt.Name + MetaTable.SummarySuffix); if (mt2 != null) { mc2 = mt2.GetMetaColumnByName(activityMc.Name); if (mc2 == null) mc2 = mt2.GetMetaColumnByLabel(activityMc.Label); } if (mc2 != null) // same column available in summarized? { mt = mt2; activityMc = mc2; } } SMP.KeyCriteriaQc.CopyCriteriaToQueryKeyCritera(q); q.KeyCriteriaDisplay = SMP.KeyCriteriaQc.CriteriaDisplay; qt.SelectKeyOnly(); QueryColumn qc = qt.GetQueryColumnByName(activityMc.Name); qc.Selected = true; q.AddQueryTable(qt); QueryEngine qe = new QueryEngine(); List<string> keyList = qe.ExecuteQuery(q); // note that keylist may be empty if single-step query HashSet<string> keySet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); List<CompoundStructureActivityData> data = new List<CompoundStructureActivityData>(); int rowCount = 0; while (true) { object[] vo = qe.NextRow(); if (vo == null) break; CompoundStructureActivityData cd = new CompoundStructureActivityData(); string cid = (string)vo[0]; cd.Cid = cid; keySet.Add(cid); // accumulate keys object val = vo[2]; if (NullValue.IsNull(val)) continue; if (val is double) cd.Activity = (double)val; else if (val is Int32) cd.Activity = (Int32)val; else if (val is NumberMx) { NumberMx nex = val as NumberMx; cd.Activity = nex.Value; } else if (val is QualifiedNumber) { QualifiedNumber qn = val as QualifiedNumber; cd.Activity = qn.NumberValue; //if (qn.Qualifier != null && qn.Qualifier != "" && qn.Qualifier != "=") // continue; // (don't want to do this since may filter out good data (e.g. IC50 <0.0001)) } else continue; if (cd.Activity == NullValue.NullNumber) continue; data.Add(cd); rowCount++; } // Retrieve structures keyList = new List<string>(keySet); Dictionary<string, MoleculeMx> csDict = MoleculeUtil.SelectMoleculesForCidList(keyList, qt.MetaTable); // get the structures in a single step // Add structures and build/store fingerprints to data DebugLog.Message("========== Fingerprints ============"); foreach (CompoundStructureActivityData cd in data) { if (!csDict.ContainsKey(cd.Cid) || csDict[cd.Cid] == null) continue; if (cd.Cid == "111" || cd.Cid == "222") csDict = csDict; // debug MoleculeMx cs = csDict[cd.Cid]; cd.Structure = cs; FingerprintType fpType = FingerprintType.Circular; int fpSubtype = -1; if (SMP.SimilarityType == SimilaritySearchType.ECFP4) // some issue with ECFP4? { fpType = FingerprintType.Circular; fpSubtype = CircularFingerprintType.ECFP4; } else if (SMP.SimilarityType == SimilaritySearchType.Normal) { fpType = FingerprintType.MACCS; } cd.BitsetFingerprint = cs.BuildBitSetFingerprint(fpType, fpSubtype); if (cd.BitsetFingerprint == null) continue; // couldn't build fingerprint (e.g. no structure) if (Debug) DebugLog.Message(cd.Cid + ": " + Lex.Join(CdkMolUtil.GetBitSet(cd.BitsetFingerprint), ", ")); } return data; }