private void EmptyGraph(SrmDocument document) { string[] resultNames = GraphData.GetReplicateLabels(document).ToArray(); XAxis.Scale.TextLabels = resultNames; var originalTextLabels = new string[XAxis.Scale.TextLabels.Length]; Array.Copy(XAxis.Scale.TextLabels, originalTextLabels, XAxis.Scale.TextLabels.Length); OriginalXAxisLabels = originalTextLabels; ScaleAxisLabels(); // Add a missing point for each replicate name. PointPairList pointPairList = new PointPairList(); for (int i = 0; i < resultNames.Length; i++) pointPairList.Add(AreaGraphData.AreaPointPairMissing(i)); AxisChange(); }
public override void UpdateGraph(bool checkData) { _dotpLabels = new GraphObjList(); SrmDocument document = GraphSummary.DocumentUIContainer.DocumentUI; var results = document.Settings.MeasuredResults; bool resultsAvailable = results != null; Clear(); if (!resultsAvailable) { Title.Text = Resources.AreaReplicateGraphPane_UpdateGraph_No_results_available; EmptyGraph(document); return; } var selectedTreeNode = GraphSummary.StateProvider.SelectedNode as SrmTreeNode; if (selectedTreeNode == null || document.FindNode(selectedTreeNode.Path) == null) { EmptyGraph(document); return; } BarSettings.Type = BarType; Title.Text = null; DisplayTypeChrom displayType; if (Equals(PaneKey, PaneKey.PRECURSORS)) { displayType = DisplayTypeChrom.precursors; } else if (Equals(PaneKey, PaneKey.PRODUCTS)) { displayType = DisplayTypeChrom.products; } else { displayType = GraphChromatogram.GetDisplayType(document, selectedTreeNode); } DocNode selectedNode = selectedTreeNode.Model; DocNode parentNode = selectedNode; IdentityPath identityPath = selectedTreeNode.Path; bool optimizationPresent = results.Chromatograms.Contains( chrom => chrom.OptimizationFunction != null); // If the selected tree node is a transition, then its siblings are displayed. if (selectedTreeNode is TransitionTreeNode) { if (displayType == DisplayTypeChrom.single) { BarSettings.Type = BarType.Cluster; } else { SrmTreeNode parentTreeNode = selectedTreeNode.SrmParent; parentNode = parentTreeNode.Model; identityPath = parentTreeNode.Path; } } // If the selected node is a peptide with one child, then show the children, // unless chromatogram display type is total else if (selectedTreeNode is PeptideTreeNode) { var children = ((PeptideDocNode)selectedNode).TransitionGroups .Where(PaneKey.IncludesTransitionGroup) .ToArray(); if (children.Length == 1 && displayType != DisplayTypeChrom.total) { selectedNode = parentNode = children[0]; identityPath = new IdentityPath(identityPath, parentNode.Id); } else { BarSettings.Type = BarType.Cluster; } } else if (!(selectedTreeNode is TransitionGroupTreeNode)) { Title.Text = Resources.AreaReplicateGraphPane_UpdateGraph_Select_a_peptide_to_see_the_peak_area_graph; CanShowPeakAreaLegend = false; CanShowDotProduct = false; return; } var parentGroupNode = parentNode as TransitionGroupDocNode; // If a precursor is going to be displayed with display type single if (parentGroupNode != null && displayType == DisplayTypeChrom.single) { // If no optimization data, then show all the transitions if (!optimizationPresent) { displayType = DisplayTypeChrom.all; } // Otherwise, do not stack the bars else { BarSettings.Type = BarType.Cluster; } } int ratioIndex = AreaGraphData.RATIO_INDEX_NONE; var standardType = IsotopeLabelType.light; var areaView = AreaGraphController.AreaView; if (areaView == AreaNormalizeToView.area_ratio_view) { ratioIndex = GraphSummary.RatioIndex; standardType = document.Settings.PeptideSettings.Modifications.RatioInternalStandardTypes[ratioIndex]; } else if (areaView == AreaNormalizeToView.area_global_standard_view) { if (document.Settings.HasGlobalStandardArea) { ratioIndex = ChromInfo.RATIO_INDEX_GLOBAL_STANDARDS; } else { areaView = AreaNormalizeToView.none; } } // Sets normalizeData to optimization, maximum_stack, maximum, total, or none AreaNormalizeToData normalizeData; if (optimizationPresent && displayType == DisplayTypeChrom.single && areaView == AreaNormalizeToView.area_percent_view) { normalizeData = AreaNormalizeToData.optimization; } else if (areaView == AreaNormalizeToView.area_maximum_view) { normalizeData = BarSettings.Type == BarType.Stack ? AreaNormalizeToData.maximum_stack : AreaNormalizeToData.maximum; } else if (BarSettings.Type == BarType.PercentStack) { normalizeData = AreaNormalizeToData.total; } else { normalizeData = AreaNormalizeToData.none; } // Calculate graph data points // IsExpectedVisible depends on ExpectedVisible ExpectedVisible = AreaExpectedValue.none; if (parentGroupNode != null && displayType != DisplayTypeChrom.total && areaView != AreaNormalizeToView.area_ratio_view && !(optimizationPresent && displayType == DisplayTypeChrom.single)) { var displayTrans = GraphChromatogram.GetDisplayTransitions(parentGroupNode, displayType).ToArray(); bool isShowingMs = displayTrans.Any(nodeTran => nodeTran.IsMs1); bool isShowingMsMs = displayTrans.Any(nodeTran => !nodeTran.IsMs1); bool isFullScanMs = document.Settings.TransitionSettings.FullScan.IsEnabledMs && isShowingMs; if (isFullScanMs) { if (!isShowingMsMs && parentGroupNode.HasIsotopeDist) { ExpectedVisible = AreaExpectedValue.isotope_dist; } } else { if (parentGroupNode.HasLibInfo) { ExpectedVisible = AreaExpectedValue.library; } } } var expectedValue = IsExpectedVisible ? ExpectedVisible : AreaExpectedValue.none; var replicateGroupOp = GraphValues.ReplicateGroupOp.FromCurrentSettings(document.Settings); var graphData = new AreaGraphData(document, parentNode, displayType, replicateGroupOp, ratioIndex, normalizeData, expectedValue, PaneKey); var aggregateOp = replicateGroupOp.AggregateOp; // Avoid stacking CVs if (aggregateOp.Cv || aggregateOp.CvDecimal) { BarSettings.Type = BarType.Cluster; } int countNodes = graphData.DocNodes.Count; if (countNodes == 0) { ExpectedVisible = AreaExpectedValue.none; } CanShowDotProduct = ExpectedVisible != AreaExpectedValue.none && areaView != AreaNormalizeToView.area_percent_view; CanShowPeakAreaLegend = countNodes != 0; InitFromData(graphData); // Add data to the graph int selectedReplicateIndex = SelectedIndex; if (IsExpectedVisible) { if (GraphSummary.ActiveLibrary) { selectedReplicateIndex = 0; } } double maxArea = -double.MaxValue; double sumArea = 0; // An array to keep track of height of all bars to determine // where each dot product annotation (if showing) should be placed var sumAreas = new double[graphData.ReplicateGroups.Count]; // If only one bar to show, then use cluster instead of stack bar type, since nothing to stack // Important for mean error bar checking below if (BarSettings.Type == BarType.Stack && countNodes == 1 && graphData.PointPairLists[0].Count == 1) { BarSettings.Type = BarType.Cluster; } int colorOffset = 0; if (parentGroupNode != null) { // We want the product ion colors to stay the same whether they are displayed: // 1. In a single pane with the precursor ions (Transitions -> All) // 2. In a separate pane of the split graph (Transitions -> All AND Transitions -> Split Graph) // 3. In a single pane by themselves (Transition -> Products) // We will use an offset in the colors array for cases 2 and 3 so that we do not reuse the precursor ion colors. var nodeDisplayType = GraphChromatogram.GetDisplayType(document, selectedTreeNode); if (displayType == DisplayTypeChrom.products && (nodeDisplayType != DisplayTypeChrom.single || (nodeDisplayType == DisplayTypeChrom.single && !optimizationPresent))) { colorOffset = GraphChromatogram.GetDisplayTransitions(parentGroupNode, DisplayTypeChrom.precursors).Count(); } } int iColor = 0, iCharge = -1; int?charge = null; int countLabelTypes = document.Settings.PeptideSettings.Modifications.CountLabelTypes; for (int i = 0; i < countNodes; i++) { var docNode = graphData.DocNodes[i]; var pointPairLists = graphData.PointPairLists[i]; int numSteps = pointPairLists.Count / 2; for (int iStep = 0; iStep < pointPairLists.Count; iStep++) { int step = iStep - numSteps; var pointPairList = pointPairLists[iStep]; Color color; var nodeGroup = docNode as TransitionGroupDocNode; if (parentNode is PeptideDocNode) { int iColorGroup = GetColorIndex(nodeGroup, countLabelTypes, ref charge, ref iCharge); color = COLORS_GROUPS[iColorGroup % COLORS_GROUPS.Length]; } else if (displayType == DisplayTypeChrom.total) { color = COLORS_GROUPS[iColor % COLORS_GROUPS.Length]; } else if (docNode.Equals(selectedNode) && step == 0) { color = ChromGraphItem.ColorSelected; } else { color = COLORS_TRANSITION[(iColor + colorOffset) % COLORS_TRANSITION.Length]; } iColor++; // If showing ratios, do not add the standard type to the graph, // since it will always be empty, but make sure the colors still // correspond with the other graphs. if (nodeGroup != null && ratioIndex >= 0) { var labelType = nodeGroup.TransitionGroup.LabelType; if (ReferenceEquals(labelType, standardType)) { continue; } } string label = graphData.DocNodeLabels[i]; if (step != 0) { label = string.Format(Resources.AreaReplicateGraphPane_UpdateGraph_Step__0_, step); } BarItem curveItem; // Only use a MeanErrorBarItem if bars are not going to be stacked. // TODO(nicksh): AreaGraphData.NormalizeTo does not know about MeanErrorBarItem if (BarSettings.Type != BarType.Stack && BarSettings.Type != BarType.PercentStack && normalizeData == AreaNormalizeToData.none) { curveItem = new MeanErrorBarItem(label, pointPairList, color, Color.Black); } else { curveItem = new BarItem(label, pointPairList, color); } if (0 <= selectedReplicateIndex && selectedReplicateIndex < pointPairList.Count) { PointPair pointPair = pointPairList[selectedReplicateIndex]; if (!pointPair.IsInvalid) { sumArea += pointPair.Y; maxArea = Math.Max(maxArea, pointPair.Y); } } // Add area for this transition to each area entry AddAreasToSums(pointPairList, sumAreas); curveItem.Bar.Border.IsVisible = false; curveItem.Bar.Fill.Brush = new SolidBrush(color); curveItem.Tag = new IdentityPath(identityPath, docNode.Id); CurveList.Add(curveItem); } } ParentGroupNode = parentGroupNode; SumAreas = sumAreas; // Draw a box around the currently selected replicate if (ShowSelection && maxArea > -double.MaxValue) { double yValue; switch (BarSettings.Type) { case BarType.Stack: // The Math.Min(sumArea, .999) makes sure that if graph is in normalized view // height of the selection rectangle does not exceed 1, so that top of the rectangle // can be viewed when y-axis scale maximum is at 1 yValue = (areaView == AreaNormalizeToView.area_maximum_view ? Math.Min(sumArea, .999) : sumArea); break; case BarType.PercentStack: yValue = 99.99; break; default: // Scale the selection box to fit exactly the bar height yValue = (areaView == AreaNormalizeToView.area_maximum_view ? Math.Min(maxArea, .999) : maxArea); break; } GraphObjList.Add(new BoxObj(selectedReplicateIndex + .5, yValue, 0.99, yValue, Color.Black, Color.Empty) { IsClippedToChartRect = true, }); } // Reset the scale when the parent node changes bool resetAxes = (_parentNode == null || !ReferenceEquals(_parentNode.Id, parentNode.Id)); _parentNode = parentNode; UpdateAxes(resetAxes, aggregateOp, normalizeData, areaView, standardType); }
public override void UpdateGraph(bool checkData) { _dotpLabels = new GraphObjList(); SrmDocument document = GraphSummary.DocumentUIContainer.DocumentUI; var results = document.Settings.MeasuredResults; bool resultsAvailable = results != null; Clear(); if (!resultsAvailable) { Title.Text = Resources.AreaReplicateGraphPane_UpdateGraph_No_results_available; EmptyGraph(document); return; } var selectedTreeNode = GraphSummary.StateProvider.SelectedNode as SrmTreeNode; if (selectedTreeNode == null || document.FindNode(selectedTreeNode.Path) == null) { EmptyGraph(document); return; } BarSettings.Type = BarType; Title.Text = null; DisplayTypeChrom displayType; if (Equals(PaneKey, PaneKey.PRECURSORS)) { displayType = DisplayTypeChrom.precursors; } else if (Equals(PaneKey, PaneKey.PRODUCTS)) { displayType = DisplayTypeChrom.products; } else { displayType = GraphChromatogram.GetDisplayType(document, selectedTreeNode); } DocNode selectedNode = selectedTreeNode.Model; DocNode parentNode = selectedNode; IdentityPath identityPath = selectedTreeNode.Path; bool optimizationPresent = results.Chromatograms.Contains( chrom => chrom.OptimizationFunction != null); // If the selected tree node is a transition, then its siblings are displayed. if (selectedTreeNode is TransitionTreeNode) { if (displayType == DisplayTypeChrom.single) { BarSettings.Type = BarType.Cluster; } else { SrmTreeNode parentTreeNode = selectedTreeNode.SrmParent; parentNode = parentTreeNode.Model; identityPath = parentTreeNode.Path; } } // If the selected node is a peptide with one child, then show the children, // unless chromatogram display type is total else if (selectedTreeNode is PeptideTreeNode) { var children = ((PeptideDocNode) selectedNode).TransitionGroups .Where(PaneKey.IncludesTransitionGroup) .ToArray(); if (children.Length == 1 && displayType != DisplayTypeChrom.total) { selectedNode = parentNode = children[0]; identityPath = new IdentityPath(identityPath, parentNode.Id); } else { BarSettings.Type = BarType.Cluster; } } else if (!(selectedTreeNode is TransitionGroupTreeNode)) { Title.Text = Resources.AreaReplicateGraphPane_UpdateGraph_Select_a_peptide_to_see_the_peak_area_graph; CanShowPeakAreaLegend = false; CanShowDotProduct = false; return; } var parentGroupNode = parentNode as TransitionGroupDocNode; // If a precursor is going to be displayed with display type single if (parentGroupNode != null && displayType == DisplayTypeChrom.single) { // If no optimization data, then show all the transitions if (!optimizationPresent) displayType = DisplayTypeChrom.all; // Otherwise, do not stack the bars else BarSettings.Type = BarType.Cluster; } int ratioIndex = AreaGraphData.RATIO_INDEX_NONE; var standardType = IsotopeLabelType.light; var areaView = AreaGraphController.AreaView; if (areaView == AreaNormalizeToView.area_ratio_view) { ratioIndex = GraphSummary.RatioIndex; standardType = document.Settings.PeptideSettings.Modifications.RatioInternalStandardTypes[ratioIndex]; } else if (areaView == AreaNormalizeToView.area_global_standard_view) { if (document.Settings.HasGlobalStandardArea) ratioIndex = ChromInfo.RATIO_INDEX_GLOBAL_STANDARDS; else areaView = AreaNormalizeToView.none; } // Sets normalizeData to optimization, maximum_stack, maximum, total, or none AreaNormalizeToData normalizeData; if (optimizationPresent && displayType == DisplayTypeChrom.single && areaView == AreaNormalizeToView.area_percent_view) { normalizeData = AreaNormalizeToData.optimization; } else if (areaView == AreaNormalizeToView.area_maximum_view) { normalizeData = BarSettings.Type == BarType.Stack ? AreaNormalizeToData.maximum_stack : AreaNormalizeToData.maximum; } else if (BarSettings.Type == BarType.PercentStack) { normalizeData = AreaNormalizeToData.total; } else { normalizeData = AreaNormalizeToData.none; } // Calculate graph data points // IsExpectedVisible depends on ExpectedVisible ExpectedVisible = AreaExpectedValue.none; if (parentGroupNode != null && displayType != DisplayTypeChrom.total && areaView != AreaNormalizeToView.area_ratio_view && !(optimizationPresent && displayType == DisplayTypeChrom.single)) { var displayTrans = GraphChromatogram.GetDisplayTransitions(parentGroupNode, displayType).ToArray(); bool isShowingMs = displayTrans.Any(nodeTran => nodeTran.IsMs1); bool isShowingMsMs = displayTrans.Any(nodeTran => !nodeTran.IsMs1); bool isFullScanMs = document.Settings.TransitionSettings.FullScan.IsEnabledMs && isShowingMs; if (isFullScanMs) { if (!isShowingMsMs && parentGroupNode.HasIsotopeDist) ExpectedVisible = AreaExpectedValue.isotope_dist; } else { if (parentGroupNode.HasLibInfo) ExpectedVisible = AreaExpectedValue.library; } } var expectedValue = IsExpectedVisible ? ExpectedVisible : AreaExpectedValue.none; var replicateGroupOp = GraphValues.ReplicateGroupOp.FromCurrentSettings(document.Settings); var graphData = new AreaGraphData(document, parentNode, displayType, replicateGroupOp, ratioIndex, normalizeData, expectedValue, PaneKey); var aggregateOp = replicateGroupOp.AggregateOp; // Avoid stacking CVs if (aggregateOp.Cv || aggregateOp.CvDecimal) BarSettings.Type = BarType.Cluster; int countNodes = graphData.DocNodes.Count; if (countNodes == 0) ExpectedVisible = AreaExpectedValue.none; CanShowDotProduct = ExpectedVisible != AreaExpectedValue.none && areaView != AreaNormalizeToView.area_percent_view; CanShowPeakAreaLegend = countNodes != 0; InitFromData(graphData); // Add data to the graph int selectedReplicateIndex = SelectedIndex; if (IsExpectedVisible) { if (GraphSummary.ActiveLibrary) selectedReplicateIndex = 0; } double maxArea = -double.MaxValue; double sumArea = 0; // An array to keep track of height of all bars to determine // where each dot product annotation (if showing) should be placed var sumAreas = new double[graphData.ReplicateGroups.Count]; // If only one bar to show, then use cluster instead of stack bar type, since nothing to stack // Important for mean error bar checking below if (BarSettings.Type == BarType.Stack && countNodes == 1 && graphData.PointPairLists[0].Count == 1) BarSettings.Type = BarType.Cluster; int colorOffset = 0; if(parentGroupNode != null) { // We want the product ion colors to stay the same whether they are displayed: // 1. In a single pane with the precursor ions (Transitions -> All) // 2. In a separate pane of the split graph (Transitions -> All AND Transitions -> Split Graph) // 3. In a single pane by themselves (Transition -> Products) // We will use an offset in the colors array for cases 2 and 3 so that we do not reuse the precursor ion colors. var nodeDisplayType = GraphChromatogram.GetDisplayType(document, selectedTreeNode); if (displayType == DisplayTypeChrom.products && (nodeDisplayType != DisplayTypeChrom.single || (nodeDisplayType == DisplayTypeChrom.single && !optimizationPresent))) { colorOffset = GraphChromatogram.GetDisplayTransitions(parentGroupNode, DisplayTypeChrom.precursors).Count(); } } int iColor = 0, iCharge = -1; int? charge = null; int countLabelTypes = document.Settings.PeptideSettings.Modifications.CountLabelTypes; for (int i = 0; i < countNodes; i++) { var docNode = graphData.DocNodes[i]; var pointPairLists = graphData.PointPairLists[i]; int numSteps = pointPairLists.Count/2; for (int iStep = 0; iStep < pointPairLists.Count; iStep++) { int step = iStep - numSteps; var pointPairList = pointPairLists[iStep]; Color color; var nodeGroup = docNode as TransitionGroupDocNode; if (parentNode is PeptideDocNode) { int iColorGroup = GetColorIndex(nodeGroup, countLabelTypes, ref charge, ref iCharge); color = COLORS_GROUPS[iColorGroup % COLORS_GROUPS.Length]; } else if (displayType == DisplayTypeChrom.total) { color = COLORS_GROUPS[iColor%COLORS_GROUPS.Length]; } else if (docNode.Equals(selectedNode) && step == 0) { color = ChromGraphItem.ColorSelected; } else { color = COLORS_TRANSITION[(iColor + colorOffset) % COLORS_TRANSITION.Length]; } iColor++; // If showing ratios, do not add the standard type to the graph, // since it will always be empty, but make sure the colors still // correspond with the other graphs. if (nodeGroup != null && ratioIndex >= 0) { var labelType = nodeGroup.TransitionGroup.LabelType; if (ReferenceEquals(labelType, standardType)) continue; } string label = graphData.DocNodeLabels[i]; if (step != 0) label = string.Format(Resources.AreaReplicateGraphPane_UpdateGraph_Step__0_, step); BarItem curveItem; // Only use a MeanErrorBarItem if bars are not going to be stacked. // TODO(nicksh): AreaGraphData.NormalizeTo does not know about MeanErrorBarItem if (BarSettings.Type != BarType.Stack && BarSettings.Type != BarType.PercentStack && normalizeData == AreaNormalizeToData.none) { curveItem = new MeanErrorBarItem(label, pointPairList, color, Color.Black); } else { curveItem = new BarItem(label, pointPairList, color); } if (0 <= selectedReplicateIndex && selectedReplicateIndex < pointPairList.Count) { PointPair pointPair = pointPairList[selectedReplicateIndex]; if (!pointPair.IsInvalid) { sumArea += pointPair.Y; maxArea = Math.Max(maxArea, pointPair.Y); } } // Add area for this transition to each area entry AddAreasToSums(pointPairList, sumAreas); curveItem.Bar.Border.IsVisible = false; curveItem.Bar.Fill.Brush = new SolidBrush(color); curveItem.Tag = new IdentityPath(identityPath, docNode.Id); CurveList.Add(curveItem); } } ParentGroupNode = parentGroupNode; SumAreas = sumAreas; // Draw a box around the currently selected replicate if (ShowSelection && maxArea > -double.MaxValue) { double yValue; switch (BarSettings.Type) { case BarType.Stack: // The Math.Min(sumArea, .999) makes sure that if graph is in normalized view // height of the selection rectangle does not exceed 1, so that top of the rectangle // can be viewed when y-axis scale maximum is at 1 yValue = (areaView == AreaNormalizeToView.area_maximum_view ? Math.Min(sumArea, .999) : sumArea); break; case BarType.PercentStack: yValue = 99.99; break; default: // Scale the selection box to fit exactly the bar height yValue = (areaView == AreaNormalizeToView.area_maximum_view ? Math.Min(maxArea, .999) : maxArea); break; } GraphObjList.Add(new BoxObj(selectedReplicateIndex + .5, yValue, 0.99, yValue, Color.Black, Color.Empty) { IsClippedToChartRect = true, }); } // Reset the scale when the parent node changes bool resetAxes = (_parentNode == null || !ReferenceEquals(_parentNode.Id, parentNode.Id)); _parentNode = parentNode; UpdateAxes(resetAxes, aggregateOp, normalizeData, areaView, standardType); }