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)); } }
public static Size RenderTip(PeptideDocNode nodePep, TransitionGroupDocNode nodeGroup, TransitionDocNode nodeTranSelected, SrmSettings settings, Graphics g, Size sizeMax, bool draw) { if (nodeGroup.TransitionGroup.IsCustomIon) { var customTable = new TableDesc(); using (RenderTools rt = new RenderTools()) { customTable.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Molecule, nodeGroup.CustomIon.Name, rt); customTable.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_charge, nodeGroup.TransitionGroup.PrecursorCharge.ToString(LocalizationHelper.CurrentCulture), rt); customTable.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_mz, string.Format("{0:F04}", nodeGroup.PrecursorMz), rt); // Not L10N if (nodeGroup.CustomIon.Formula != null) { customTable.AddDetailRow(Resources.TransitionTreeNode_RenderTip_Formula, nodeGroup.CustomIon.Formula, 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 = GetChoices(nodeGroup, 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); string aa = nodeGroup.TransitionGroup.Peptide.Sequence; // We handled custom ions above, and returned double[,] masses = calc.GetFragmentIonMasses(aa); var filter = settings.TransitionSettings.Filter; // Get charges and type pairs, making sure all chosen charges are included HashSet<int> setCharges = new HashSet<int>(filter.ProductCharges.Where(charge => Math.Abs(charge) <= Math.Abs(nodeGroup.TransitionGroup.PrecursorCharge) && Math.Sign(charge) == Math.Sign(nodeGroup.TransitionGroup.PrecursorCharge))); HashSet<IonType> setTypes = new HashSet<IonType>(filter.IonTypes); foreach (TransitionDocNode nodTran in chosen) { var type = nodTran.Transition.IonType; if (type == IonType.precursor) continue; setCharges.Add(nodTran.Transition.Charge); setTypes.Add(type); } setTypes.Remove(IonType.precursor); int[] charges = setCharges.ToArray(); Array.Sort(charges); IonType[] types = Transition.GetTypePairs(setTypes); var tableDetails = new TableDesc(); var table = new TableDesc(); using (RenderTools rt = new RenderTools()) { string seqModified = GetModifiedSequence(nodePep, nodeGroup, settings); if (!Equals(seqModified, nodeGroup.TransitionGroup.Peptide.Sequence)) tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Modified, seqModified, rt); var precursorCharge = nodeGroup.TransitionGroup.PrecursorCharge; var precursorMz = nodeGroup.PrecursorMz; tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_charge, precursorCharge.ToString(LocalizationHelper.CurrentCulture), rt); tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_mz, string.Format("{0:F04}", precursorMz), rt); // Not L10N tableDetails.AddDetailRow(Resources.TransitionGroupTreeNode_RenderTip_Precursor_mh, string.Format("{0:F04}", nodeGroup.GetPrecursorIonMass()), // Not L10N 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), // Not L10N CreateHead("AA", rt), // Not L10N CreateHead("#", rt) // Not L10N }; foreach (int 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 (int charge in charges) { foreach (IonType type in types) { CellDesc cell; if (Transition.IsNTerminal(type)) { if (i == len - 1) cell = CreateData(string.Empty, rt); else { double massH = masses[(int)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 { double massH = masses[(int)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); } }