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();
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }