private static CellDesc CreateIon(IonType type, int ordinal, TypedMass massH, Adduct charge, IEnumerable <DocNode> choices, ICollection <DocNode> chosen, Transition tranSelected, RenderTools rt) { double mz = SequenceMassCalc.GetMZ(massH, charge); CellDesc cell = CreateData(string.Format(@"{0:F02}", mz), rt); foreach (TransitionDocNode nodeTran in choices) { Transition tran = nodeTran.Transition; if (tran.IonType == type && tran.Ordinal == ordinal && tran.Adduct == charge) { cell.Font = rt.FontBold; if (Equals(tran, tranSelected)) { cell.Brush = rt.BrushSelected; // Stop after selected break; } if (!chosen.Contains(nodeTran)) { cell.Brush = rt.BrushChoice; // Keep looking } else { cell.Brush = rt.BrushChosen; // Stop after chosen break; } } } return(cell); }
public static Size RenderTip(PeptideDocNode nodePep, TransitionGroupDocNode nodeGroup, TransitionDocNode nodeTranSelected, SrmSettings settings, Graphics g, Size sizeMax, bool draw) { if (nodeGroup.TransitionGroup.IsCustomIon) // TODO(bspratt) this seems to leave out a lot of detail { var customTable = new TableDesc(); using (RenderTools rt = new RenderTools()) { customTable.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Molecule, nodeGroup.CustomMolecule.Name, rt); customTable.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_charge, nodeGroup.TransitionGroup.PrecursorAdduct.AdductCharge.ToString(LocalizationHelper.CurrentCulture), rt); customTable.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_mz, string.Format(@"{0:F04}", nodeGroup.PrecursorMz), rt); if (nodeGroup.CustomMolecule.Formula != null) { customTable.AddDetailRow(Resources.TransitionTreeNode_RenderTip_Formula, nodeGroup.CustomMolecule.Formula + nodeGroup.TransitionGroup.PrecursorAdduct.AdductFormula.ToString(LocalizationHelper.CurrentCulture), rt); } SizeF size = customTable.CalcDimensions(g); customTable.Draw(g); return(new Size((int)size.Width + 2, (int)size.Height + 2)); } } ExplicitMods mods = (nodePep != null ? nodePep.ExplicitMods : null); IEnumerable <DocNode> choices = nodeGroup.GetPrecursorChoices(settings, mods, true).ToArray(); HashSet <DocNode> chosen = new HashSet <DocNode>(nodeGroup.Children); // Make sure all chosen peptides get listed HashSet <DocNode> setChoices = new HashSet <DocNode>(choices); setChoices.UnionWith(chosen); choices = setChoices.ToArray(); Transition tranSelected = (nodeTranSelected != null ? nodeTranSelected.Transition : null); IFragmentMassCalc calc = settings.GetFragmentCalc(nodeGroup.TransitionGroup.LabelType, mods); var aa = nodeGroup.TransitionGroup.Peptide.Target.Sequence; // We handled custom ions above, and returned var masses = calc.GetFragmentIonMasses(nodeGroup.TransitionGroup.Peptide.Target); var filter = settings.TransitionSettings.Filter; // Get charges and type pairs, making sure all chosen charges are included var setCharges = new HashSet <Adduct>(filter.PeptideProductCharges.Where(charge => Math.Abs(charge.AdductCharge) <= Math.Abs(nodeGroup.TransitionGroup.PrecursorCharge) && Math.Sign(charge.AdductCharge) == Math.Sign(nodeGroup.TransitionGroup.PrecursorCharge))); HashSet <IonType> setTypes = new HashSet <IonType>(filter.PeptideIonTypes); foreach (TransitionDocNode nodTran in chosen) { var type = nodTran.Transition.IonType; if (!Transition.IsPeptideFragment(type)) { continue; } setCharges.Add(nodTran.Transition.Adduct); setTypes.Add(type); } setTypes.RemoveWhere(t => !Transition.IsPeptideFragment(t)); var charges = setCharges.Where(c => c.IsProteomic).ToArray(); Array.Sort(charges); IonType[] types = Transition.GetTypePairs(setTypes); var tableDetails = new TableDesc(); var table = new TableDesc(); using (RenderTools rt = new RenderTools()) { var seqModified = GetModifiedSequence(nodePep, nodeGroup, settings); if (!Equals(seqModified, nodeGroup.TransitionGroup.Peptide.Target)) { tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Modified, seqModified.Sequence, rt); } var precursorCharge = nodeGroup.TransitionGroup.PrecursorAdduct; var precursorMz = nodeGroup.PrecursorMz; tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_charge, precursorCharge.AdductCharge.ToString(LocalizationHelper.CurrentCulture), rt); tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_mz, string.Format(@"{0:F04}", precursorMz), rt); tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_mh, string.Format(@"{0:F04}", nodeGroup.GetPrecursorIonMass()), rt); int?decoyMassShift = nodeGroup.TransitionGroup.DecoyMassShift; if (decoyMassShift.HasValue) { tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Decoy_Mass_Shift, decoyMassShift.Value.ToString(LocalizationHelper.CurrentCulture), rt); } if (nodeGroup.HasLibInfo) { foreach (KeyValuePair <PeptideRankId, string> pair in nodeGroup.LibInfo.RankValues) { tableDetails.AddDetailRow(pair.Key.Label, pair.Value, rt); } } if (charges.Length > 0 && types.Length > 0) { var headers = new RowDesc { CreateHead(@"#", rt), CreateHead(@"AA", rt), CreateHead(@"#", rt) }; foreach (var charge in charges) { string plusSub = Transition.GetChargeIndicator(charge); foreach (IonType type in types) { CellDesc cell = CreateHead(type.ToString().ToLower() + plusSub, rt); if (Transition.IsNTerminal(type)) { headers.Insert(0, cell); } else { headers.Add(cell); } } } table.Add(headers); int len = aa.Length; for (int i = 0; i < len; i++) { CellDesc cellAA = CreateRowLabel(aa.Substring(i, 1), rt); cellAA.Align = StringAlignment.Center; var row = new RowDesc { CreateRowLabel(i == len - 1 ? string.Empty : (i + 1).ToString(CultureInfo.InvariantCulture), rt), cellAA, CreateRowLabel(i == 0 ? string.Empty : (len - i).ToString(CultureInfo.InvariantCulture), rt) }; foreach (var charge in charges) { foreach (IonType type in types) { CellDesc cell; if (Transition.IsNTerminal(type)) { if (i == len - 1) { cell = CreateData(string.Empty, rt); } else { var massH = masses[type, i]; cell = CreateIon(type, i + 1, massH, charge, choices, chosen, tranSelected, rt); } row.Insert(0, cell); } else { if (i == 0) { cell = CreateData(string.Empty, rt); } else { var massH = masses[type, i - 1]; cell = CreateIon(type, len - i, massH, charge, choices, chosen, tranSelected, rt); } row.Add(cell); } } } table.Add(row); } } SizeF sizeDetails = tableDetails.CalcDimensions(g); sizeDetails.Height += TableDesc.TABLE_SPACING; // Spacing between details and fragments SizeF size = table.CalcDimensions(g); if (draw) { tableDetails.Draw(g); g.TranslateTransform(0, sizeDetails.Height); table.Draw(g); g.TranslateTransform(0, -sizeDetails.Height); } int width = (int)Math.Round(Math.Max(sizeDetails.Width, size.Width)); int height = (int)Math.Round(sizeDetails.Height + size.Height); return(new Size(width + 2, height + 2)); } }