public void SetThreshold(double?value) { if (value.HasValue) { if (m_Threshold == null) { m_Threshold = new LineObj(Color.Red, 0, value.Value, 1, value.Value) { Location = { CoordinateFrame = CoordType.XChartFractionYScale }, IsClippedToChartRect = true }; GraphObjList.Add(m_Threshold); } else { m_Threshold.Location.Y = value.Value; } } else { GraphObjList.Remove(m_Threshold); m_Threshold = null; } m_Parent.UpdateGraph(); }
private void AddAnnotations(Graphics g) { foreach (GraphObj obj in _pointAnnotations) { TextObj text = obj as TextObj; if (text != null) { if (text.Location.CoordinateFrame == CoordType.ChartFraction && text.Location.AlignH == AlignH.Left && text.Location.AlignV == AlignV.Top) { GraphObjList.Add(text); continue; } if (isXChartFractionObject(text) && (text.Location.X < XAxis.Scale.Min || text.Location.X > XAxis.Scale.Max)) { continue; } var textRect = _labelBoundsCache.GetLabelBounds(text, this, g); if (_overlapDetector == null || !_overlapDetector.Overlaps(textRect)) { _manualLabels[text] = textRect; } } else if (!GraphObjList.Contains(obj)) // always add non-text annotations { GraphObjList.Add(obj); } } }
private void AddDotProductLabels(Graphics g, TransitionGroupDocNode nodeGroup, IList <double> sumAreas) { // Create temporary label to calculate positions var pointSize = GetDotProductsPointSize(g); bool visible = pointSize.HasValue; bool visibleState = _dotpLabels.Count > 0; if (visible == visibleState && (!visibleState || ((TextObj)_dotpLabels[0]).FontSpec.Size == pointSize)) { return; } foreach (GraphObj pa in _dotpLabels) { GraphObjList.Remove(pa); } _dotpLabels.Clear(); if (visible) { // x shift of the dot product labels var xShift = 1; if (IsExpectedVisible) { // shift dot product labels over by 1 more, if library is visible xShift++; } for (int i = 0; i < sumAreas.Count; i++) { string text = GetDotProductResultsText(nodeGroup, i); if (string.IsNullOrEmpty(text)) { continue; } TextObj textObj = new TextObj(text, i + xShift, sumAreas[i], CoordType.AxisXYScale, AlignH.Center, AlignV.Bottom) { IsClippedToChartRect = true, ZOrder = ZOrder.F_BehindGrid, }; textObj.FontSpec.Border.IsVisible = false; textObj.FontSpec.Size = pointSize.Value; _lableHeight = (int)textObj.FontSpec.GetHeight(CalcScaleFactor()); GraphObjList.Add(textObj); _dotpLabels.Add(textObj); } } }
public override void Draw(Graphics g) { GraphObjList.Clear(); if (_graphData != null) { // Force Axes to recalculate to ensure proper layout of labels AxisChange(g); // Reposition the regression label. RectangleF rectChart = Chart.Rect; PointF ptTop = rectChart.Location; // Setup axes scales to enable the ReverseTransform method XAxis.Scale.SetupScaleData(this, XAxis); YAxis.Scale.SetupScaleData(this, YAxis); float yNext = ptTop.Y; double left = XAxis.Scale.ReverseTransform(ptTop.X + 8); FontSpec fontSpec = GraphSummary.CreateFontSpec(COLOR_LINE_REGRESSION); if (_labelRegression != null) { // Add regression text double top = YAxis.Scale.ReverseTransform(yNext); TextObj text = new TextObj(_labelRegression, left, top, CoordType.AxisXYScale, AlignH.Left, AlignV.Top) { IsClippedToChartRect = true, ZOrder = ZOrder.E_BehindCurves, FontSpec = fontSpec, }; // text.FontSpec.Size = 12; GraphObjList.Add(text); } if (_labelRegressionCurrent != null) { // Add text for current regression SizeF sizeLabel = fontSpec.MeasureString(g, _labelRegression, CalcScaleFactor()); yNext += sizeLabel.Height + 3; double top = YAxis.Scale.ReverseTransform(yNext); TextObj text = new TextObj(_labelRegressionCurrent, left, top, CoordType.AxisXYScale, AlignH.Left, AlignV.Top) { IsClippedToChartRect = true, ZOrder = ZOrder.E_BehindCurves, FontSpec = GraphSummary.CreateFontSpec(COLOR_LINE_REGRESSION_CURRENT), }; // text.FontSpec.Size = 12; GraphObjList.Add(text); } } base.Draw(g); }
private void AddRetentionTimeAnnotation(MSGraphPane graphPane, Graphics g, GraphObjList annotations, PointF ptTop, string title, GraphObjType graphObjType, Color color, ScaledRetentionTime retentionTime) { // ReSharper disable LocalizableElement string label = string.Format("{0}\n{1:F01}", title, retentionTime.DisplayTime); // ReSharper restore LocalizableElement FontSpec fontLabel = CreateFontSpec(color, _fontSpec.Size); SizeF sizeLabel = fontLabel.MeasureString(g, label, graphPane.CalcScaleFactor()); PointF realTopPoint = ptTop; ptTop = new PointF(0, ptTop.Y + sizeLabel.Height + 15); float chartHeightWithLabel = graphPane.Chart.Rect.Height + sizeLabel.Height + 15; double intensityChartFraction = (ptTop.Y - realTopPoint.Y) / chartHeightWithLabel; LineObj stick = new LineObj(color, retentionTime.DisplayTime, intensityChartFraction, retentionTime.DisplayTime, 1) { IsClippedToChartRect = true, Location = { CoordinateFrame = CoordType.XScaleYChartFraction }, ZOrder = ZOrder.E_BehindCurves, Line = { Width = 1 }, Tag = new GraphObjTag(this, graphObjType, retentionTime), }; annotations.Add(stick); ptTop = new PointF(0, ptTop.Y - 5); intensityChartFraction = (ptTop.Y - realTopPoint.Y) / chartHeightWithLabel; TextObj text = new TextObj(label, retentionTime.DisplayTime, intensityChartFraction, CoordType.XScaleYChartFraction, AlignH.Center, AlignV.Bottom) { IsClippedToChartRect = true, ZOrder = ZOrder.E_BehindCurves, FontSpec = CreateFontSpec(color, _fontSpec.Size), Tag = new GraphObjTag(this, graphObjType, retentionTime), }; annotations.Add(text); }
public void addEquity(Simulator simulator) { Bomb.when(Objects.hasContent(equity), () => "equity has content already: " + Objects.toShortString(equity)); equity.AddRange(simulator.equity(symbol)); var points = new PointPairList(); Objects.eachIt(simulator.equity(symbol), (i, value) => points.Add(i + 1, value)); var curve = AddCurve("equity", points, Color.Red); curve.Symbol.IsVisible = false; curve.IsOverrideOrdinal = true; var zero = new LineObj(Color.Gray, 1, 0, bars.count(), 0) { Line = { Style = DashStyle.Dash }, Location = { CoordinateFrame = CoordType.AxisXYScale } }; GraphObjList.Add(zero); AxisChange(); var graphable = new EquityGraphable("equity", simulator.equity(symbol), simulator.dates(symbol)); graphables.Add(graphable); var needsNewPoint = false; bars.pushedDown += () => needsNewPoint = true; bars.valueSet += bar => { var value = simulator.pnl(symbol); var todaysMarketPnl = Objects.sum(Objects.convert(simulator.positions(symbol), position => position.pnl(bars[1].close, bars[0].close))); value += todaysMarketPnl; graphable.add(bar.time, value); QControl.runOnGuiThread(dispatchTo, () => { var lastPoint = curve[curve.Points.Count - 1]; if (needsNewPoint) { curve.AddPoint(lastPoint.X + 1, value); equity.Add(value); } else { lastPoint.Y = value; equity[equity.Count - 1] = value; } BarSpudGraph.addEquityTo(Objects.first(parentTyped.dataTable().Rows), value); needsNewPoint = false; parentTyped.Invalidate(); }); }; }
public override void AddAnnotations(MSGraphPane graphPane, Graphics g, MSPointList pointList, GraphObjList annotations) { // ReSharper disable UseObjectOrCollectionInitializer foreach (var rmi in SpectrumInfo.PeaksMatched) { if (!IsVisibleIon(rmi)) { continue; } var matchedIon = rmi.MatchedIons.First(IsVisibleIon); Color color; switch (matchedIon.IonType) { default: color = COLOR_NONE; break; case IonType.a: color = COLOR_A; break; case IonType.x: color = COLOR_X; break; case IonType.b: color = COLOR_B; break; case IonType.y: color = COLOR_Y; break; case IonType.c: color = COLOR_C; break; case IonType.z: color = COLOR_Z; break; case IonType.custom: color = (rmi.Rank > 0) ? COLOR_OTHER_IONS : COLOR_NONE; break; // Small molecule fragments - only color if ranked case IonType.precursor: color = COLOR_PRECURSOR; break; } if (rmi.MatchedIons.Any(mfi => IsMatch(mfi.PredictedMz))) { color = COLOR_SELECTED; } double mz = rmi.ObservedMz; var stick = new LineObj(color, mz, rmi.Intensity, mz, 0); stick.IsClippedToChartRect = true; stick.Location.CoordinateFrame = CoordType.AxisXYScale; stick.Line.Width = LineWidth + 1; annotations.Add(stick); } //ReSharper restore UseObjectOrCollectionInitializer }
public override void AddAnnotations(MSGraphPane graphPane, Graphics g, MSPointList pointList, GraphObjList annotations) { // ReSharper disable UseObjectOrCollectionInitializer foreach (var rmi in SpectrumInfo.PeaksMatched) { if (!IsVisibleIon(rmi)) { continue; } IonType type = IsVisibleIon(rmi.IonType, rmi.Ordinal, rmi.Charge) ? rmi.IonType : rmi.IonType2; Color color; switch (type) { default: color = COLOR_NONE; break; case IonType.a: color = COLOR_A; break; case IonType.x: color = COLOR_X; break; case IonType.b: color = COLOR_B; break; case IonType.y: color = COLOR_Y; break; case IonType.c: color = COLOR_C; break; case IonType.z: color = COLOR_Z; break; // FUTURE: Add custom ions when LibraryRankedSpectrumInfo can support them case IonType.precursor: color = COLOR_PRECURSOR; break; } if (IsMatch(rmi.PredictedMz)) { color = COLOR_SELECTED; } double mz = rmi.ObservedMz; var stick = new LineObj(color, mz, rmi.Intensity, mz, 0); stick.IsClippedToChartRect = true; stick.Location.CoordinateFrame = CoordType.AxisXYScale; stick.Line.Width = LineWidth + 1; annotations.Add(stick); } //ReSharper restore UseObjectOrCollectionInitializer }
private void AddOriginalPeakAnnotation(ChromPeak bestPeak, GraphObjList annotations, GraphPane graphPane) { var start = ScaleRetentionTime(bestPeak.StartTime); var end = ScaleRetentionTime(bestPeak.EndTime); var width = end.DisplayTime - start.DisplayTime; var height = graphPane.YAxis.Scale.Max; var originalPeakShadingBox = new BoxObj(start.DisplayTime, graphPane.YAxis.Scale.Max, width, height) { Fill = new Fill(Color.FromArgb(30, COLOR_ORIGINAL_PEAK_SHADE)), ZOrder = ZOrder.F_BehindGrid, Border = new Border { IsVisible = false }, IsClippedToChartRect = true, Tag = new GraphObjTag(this, GraphObjType.original_peak_shading, start, end) }; annotations.Add(originalPeakShadingBox); }
private void AddLabels(Graphics g) { if (_areaCVGraphData == null) { Title.Text = Resources.AreaCVHistogramGraphPane_AddLabels_Calculating____; } else if (!_areaCVGraphData.IsValid) { Title.Text = Resources.AreaCVHistogramGraphPane_AddLabels_Not_enough_data; } else { Title.Text = string.Empty; var unit = _percentage ? @"%" : string.Empty; var factor = _percentage ? 100.0 : 1.0; var scaleFactor = CalcScaleFactor(); var fontHeight = GraphSummary.CreateFontSpec(Color.Black).GetHeight(scaleFactor); var height = PaneHeightToYValue(fontHeight); // Anchor labels at top of graph pane var y = Math.Min(PaneHeightToYValue(Rect.Height - TitleGap * Title.FontSpec.GetHeight(scaleFactor) - fontHeight * _stickItems.Count), _areaCVGraphData.MaxFrequency + height); var index = 0; if (Settings.Default.AreaCVShowMedianCV) { _stickItems[index++].Points[1].Y = y; string text = string.Format(Resources.AreaCVHistogramGraphPane_AddLabels_Median___0_, HistogramHelper.FormatDouble(_areaCVGraphData.MedianCV * factor, _decimals) + unit); GraphObjList.Add(AddLabel(text, _areaCVGraphData.MedianCV * factor, y, Color.Blue)); y += height; } if (Settings.Default.AreaCVShowCVCutoff) { _stickItems[index++].Points[1].Y = y; string text = string.Format(Resources.AreaCVHistogramGraphPane_UpdateGraph_Below__0____1_, Settings.Default.AreaCVCVCutoff + unit, HistogramHelper.FormatDouble(_areaCVGraphData.BelowCVCutoff * factor, _decimals) + unit); GraphObjList.Add(AddLabel(text, Settings.Default.AreaCVCVCutoff, y, Color.Red)); } } }
void addCrosshair(float x, float y) { Bomb.unlessNull(xLine, () => "addCrosshair called twice without removeCrossHair"); Bomb.unlessNull(yLine, () => "addCrosshair called twice without removeCrossHair"); var chartPoint = point(x, y); xLine = new LineObj(Color.Gray, chartPoint.X, 0, chartPoint.X, 1) { Location = { CoordinateFrame = CoordType.XScaleYChartFraction } }; yLine = new LineObj(Color.Gray, 0, chartPoint.Y, 1, chartPoint.Y) { Location = { CoordinateFrame = CoordType.XChartFractionYScale } }; Objects.each(Objects.list(xLine, yLine), line => { line.ZOrder = ZOrder.E_BehindCurves; line.Line.Style = DashStyle.Dash; }); GraphObjList.Add(xLine); GraphObjList.Add(yLine); }
private void AddSelection(int selectedReplicateIndex, double maxRetentionTime, double minRetentionTime) { bool selectLines = CurveList.Any(c => c is LineItem); if (selectLines) { GraphObjList.Add(new LineObj(Color.Black, selectedReplicateIndex + 1, 0, selectedReplicateIndex + 1, maxRetentionTime) { IsClippedToChartRect = true, Line = new Line { Width = 2, Color = Color.Black, Style = DashStyle.Dash } }); } else { GraphObjList.Add(new BoxObj(selectedReplicateIndex + .5, maxRetentionTime, 1, maxRetentionTime - minRetentionTime, Color.Black, Color.Empty) { IsClippedToChartRect = true, }); } }
public override void AddAnnotations(MSGraphPane graphPane, Graphics g, MSPointList pointList, GraphObjList annotations) { // ReSharper disable UseObjectOrCollectionInitializer foreach (var rmi in SpectrumInfo.PeaksMatched) { if (!IsVisibleIon(rmi)) { continue; } var matchedIon = rmi.MatchedIons.First(IsVisibleIon); Color color; switch (matchedIon.IonType) { default: color = COLOR_NONE; break; case IonType.a: color = COLOR_A; break; case IonType.x: color = COLOR_X; break; case IonType.b: color = COLOR_B; break; case IonType.y: color = COLOR_Y; break; case IonType.c: color = COLOR_C; break; case IonType.z: color = COLOR_Z; break; case IonType.custom: color = (rmi.Rank > 0) ? COLOR_OTHER_IONS : COLOR_NONE; break; // Small molecule fragments - only color if ranked case IonType.precursor: color = COLOR_PRECURSOR; break; } if (Invert) { color = InvertColor(color); } if (rmi.MatchedIons.Any(mfi => IsMatch(mfi.PredictedMz))) { color = COLOR_SELECTED; } double mz = rmi.ObservedMz; var intensity = Invert ? -rmi.Intensity : rmi.Intensity; var stick = new LineObj(color, mz, intensity, mz, 0); stick.IsClippedToChartRect = true; stick.Location.CoordinateFrame = CoordType.AxisXYScale; stick.Line.Width = LineWidth + 1; annotations.Add(stick); } //ReSharper restore UseObjectOrCollectionInitializer if (ShowScores && SpectrumInfo.Score.HasValue) { var text = new TextObj( string.Format(LocalizationHelper.CurrentCulture, Resources.AbstractSpectrumGraphItem_AddAnnotations_, SpectrumInfo.Score), 0.01, 0, CoordType.ChartFraction, AlignH.Left, AlignV.Top) { IsClippedToChartRect = true, ZOrder = ZOrder.E_BehindCurves, FontSpec = GraphSummary.CreateFontSpec(Color.Black), }; annotations.Add(text); } }
public override void AddPreCurveAnnotations(MSGraphPane graphPane, Graphics g, MSPointList pointList, GraphObjList annotations) { if (Chromatogram == null) { return; } // Give priority to showing the best peak text object above all other annotations if (DragInfo != null || (!HideBest && TransitionChromInfo != null) || CurveAnnotation != null) { // Show text and arrow for the best peak double intensityBest = 0; if (_bestPeakTimeIndex != -1) { ScaledRetentionTime timeBest = new ScaledRetentionTime(_measuredTimes[_bestPeakTimeIndex], _displayTimes[_bestPeakTimeIndex]); float xBest = graphPane.XAxis.Scale.Transform(timeBest.DisplayTime); intensityBest = _intensities[_bestPeakTimeIndex]; float yBest = graphPane.YAxis.Scale.Transform(intensityBest); if (GraphChromatogram.ShowRT != ShowRTChrom.none || DragInfo != null) { // Best peak gets its own label to avoid curve overlap detection double intensityLabel = graphPane.YAxis.Scale.ReverseTransform(yBest - 5); float? massError = Settings.Default.ShowMassError && TransitionChromInfo != null ? TransitionChromInfo.MassError : null; double dotProduct = _dotProducts != null ? _bestProduct : 0; TextObj text; if (CurveAnnotation != null) { // Darken peptide name a little so light colors stand out against the white background. var color = FontSpec.FontColor; if (!GraphInfo.IsSelected) { color = Color.FromArgb(color.R * 7 / 10, color.G * 7 / 10, color.B * 7 / 10); } var fontSpec = new FontSpec(FontSpec) { FontColor = color, Angle = 90 }; if (GraphInfo.IsSelected) { fontSpec = new FontSpec(fontSpec) { IsBold = true, Size = fontSpec.Size + 2, IsAntiAlias = true } } ; // Display peptide name label using vertical text. text = new TextObj(CurveAnnotation, timeBest.DisplayTime, intensityLabel, CoordType.AxisXYScale, AlignH.Left, AlignV.Center) { ZOrder = ZOrder.A_InFront, IsClippedToChartRect = true, FontSpec = fontSpec, Tag = new GraphObjTag(this, GraphObjType.best_peak, timeBest), }; } else { string label = FormatTimeLabel(timeBest.DisplayTime, massError, dotProduct); text = new TextObj(label, timeBest.DisplayTime, intensityLabel, CoordType.AxisXYScale, AlignH.Center, AlignV.Bottom) { ZOrder = ZOrder.A_InFront, IsClippedToChartRect = true, FontSpec = FontSpec, Tag = new GraphObjTag(this, GraphObjType.best_peak, timeBest), }; } annotations.Add(text); } // If showing multiple peptides, skip the best peak arrow indicator. if (CurveAnnotation == null) { // Show the best peak arrow indicator double timeArrow = graphPane.XAxis.Scale.ReverseTransform(xBest - 4); double intensityArrow = graphPane.YAxis.Scale.ReverseTransform(yBest - 2); ArrowObj arrow = new ArrowObj(COLOR_BEST_PEAK, 12f, timeArrow, intensityArrow, timeArrow, intensityArrow) { Location = { CoordinateFrame = CoordType.AxisXYScale }, IsArrowHead = true, IsClippedToChartRect = true, ZOrder = ZOrder.A_InFront }; annotations.Add(arrow); } } // Show the best peak boundary lines if (CurveAnnotation == null) { double startTime = 0, endTime = 0; if (DragInfo != null) { startTime = DragInfo.StartTime.MeasuredTime; endTime = DragInfo.EndTime.MeasuredTime; } else if (TransitionChromInfo != null) { var tranPeakInfo = TransitionChromInfo; startTime = tranPeakInfo.StartRetentionTime; endTime = tranPeakInfo.EndRetentionTime; } AddPeakBoundaries(graphPane, annotations, true, ScaleRetentionTime(startTime), ScaleRetentionTime(endTime), intensityBest); } if (Chromatogram.BestPeakIndex >= 0) { // Only shade peak when user modified. Otherwise, shading can be added when an entire // precursor was force integrated because of another precursor (e.g. heavy) since that // leads to an empty peak, which will not match the best peak. if (Settings.Default.ShowOriginalPeak && TransitionChromInfo != null && TransitionChromInfo.IsUserModified) { var bestPeak = Chromatogram.GetPeak(Chromatogram.BestPeakIndex); if (bestPeak.StartTime != TransitionChromInfo.StartRetentionTime || bestPeak.EndTime != TransitionChromInfo.EndRetentionTime) { AddOriginalPeakAnnotation(bestPeak, annotations, graphPane); } } } } if (_displayRawTimes.HasValue) { AddPeakRawTimes(graphPane, annotations, ScaleRetentionTime(_displayRawTimes.Value.StartBound), ScaleRetentionTime(_displayRawTimes.Value.EndBound), Chromatogram); } }
public override void UpdateGraph(bool selectionChanged) { Clear(); TransitionGroupDocNode selectedGroup = null; PeptideGroupDocNode selectedProtein = null; var selectedTreeNode = GraphSummary.StateProvider.SelectedNode as SrmTreeNode; if (selectedTreeNode != null) { if (selectedTreeNode is TransitionTreeNode) { selectedGroup = (TransitionGroupDocNode)selectedTreeNode.SrmParent.Model; } else if (selectedTreeNode is TransitionGroupTreeNode) { selectedGroup = (TransitionGroupDocNode)selectedTreeNode.Model; } else { var node = selectedTreeNode as PeptideTreeNode; if (node != null) { var nodePep = node.DocNode; selectedGroup = nodePep.TransitionGroups.FirstOrDefault(); } } var proteinTreeNode = selectedTreeNode.GetNodeOfType <PeptideGroupTreeNode>(); if (proteinTreeNode != null) { selectedProtein = proteinTreeNode.DocNode; } } SrmDocument document = GraphSummary.DocumentUIContainer.DocumentUI; var displayType = GraphChromatogram.GetDisplayType(document, selectedTreeNode); _graphData = CreateGraphData(document, selectedProtein, selectedGroup, displayType); int iColor = 0; int colorOffset = 0; if (selectedGroup != null && displayType == DisplayTypeChrom.products) { // If we are only displaying product ions, we want to use an offset in the colors array // so that we do not re-use colors that would be used for any precursor ions. colorOffset = GraphChromatogram.GetDisplayTransitions(selectedGroup, DisplayTypeChrom.precursors).Count(); } foreach (var pointPairList in _graphData.PointPairLists) { Color color = displayType == DisplayTypeChrom.total ? COLORS_GROUPS[iColor++ % COLORS_GROUPS.Count] : COLORS_TRANSITION[(iColor++ + colorOffset) % COLORS_TRANSITION.Count]; BarItem curveItem; if (HiLowMiddleErrorBarItem.IsHiLoMiddleErrorList(pointPairList)) { curveItem = new HiLowMiddleErrorBarItem(string.Empty, pointPairList, color, Color.Black); } else { curveItem = new MeanErrorBarItem(string.Empty, pointPairList, color, Color.Black); } curveItem.Bar.Border.IsVisible = false; curveItem.Bar.Fill.Brush = new SolidBrush(color); CurveList.Add(curveItem); } if (ShowSelection && SelectedIndex != -1) { double yValue = _graphData.SelectedMaxY; double yMin = _graphData.SelectedMinY; double height = yValue - yMin; GraphObjList.Add(new BoxObj(SelectedIndex + .5, yValue, 0.99, height, Color.Black, Color.Empty) { IsClippedToChartRect = true, }); } UpdateAxes(); }
/// <summary> /// We know which labels are overlapping the data points, but we need to make sure the labels that will be /// displayed can fit in the scale using the Min/MaxGrace properties and adjusting the label fractions if appropriate: /// TextObjs with CoordType.AxisXYScale coordinates will move proportionally with Min/MaxGrace, but ChartFraction /// coordinates will not. /// </summary> protected void autoScaleForManualLabels(Graphics g) { Axis yAxis = YAxis; bool maxAuto = yAxis.Scale.MaxAuto; try { if (maxAuto) { AxisChange(g); } double yMaxRequired = 0; foreach (var kvp in _manualLabels) { TextObj text = kvp.Key; if (text.Location.X < XAxis.Scale.Min || text.Location.X > XAxis.Scale.Max) { continue; } if (!YAxis.Scale.IsLog && !IsYChartFractionObject(text)) { double axisHeight = YAxis.Scale.Max - YAxis.Scale.Min; PointF[] pts = text.FontSpec.GetBox(g, text.Text, 0, 0, text.Location.AlignH, text.Location.AlignV, 1.0f, new SizeF()); float pixelShift = 0; var rectPeak = _labelBoundsCache.GetLabelBounds(text, this, g); foreach (var id in _manualLabels.Keys.Where(IsYChartFractionObject)) { var rectID = _labelBoundsCache.GetLabelBounds(id, this, g); // If the rectangles overlap if (Math.Min(rectID.Right, rectPeak.Right) - Math.Max(rectID.Left, rectPeak.Left) > 0 && Math.Min(rectID.Bottom, rectPeak.Bottom) - Math.Max(rectID.Top, rectPeak.Top) > 0) { pixelShift = Math.Max(rectID.Height + 7, pixelShift); // 7 pixel gap between labels } } double y2Pos = yAxis.Scale.ReverseTransform(pts[2].Y); double labelHeight = Math.Abs(yAxis.Scale.ReverseTransform(pts[0].Y - pixelShift) - y2Pos); // If separating the labels takes too much space, just revert to showing them aligned if (labelHeight >= axisHeight / 2) { labelHeight = Math.Abs(yAxis.Scale.ReverseTransform(pts[0].Y) - y2Pos); } if (labelHeight < axisHeight / 2) { // Ensure that the YAxis will have enough space to show the label. // Only do this if the labelHeight is going to take up less than half the space on the graph, because // otherwise the graph will be shrunk too much to have any useful information. // When calculating the scaling required, take into account that the height of the label // itself will not shrink when we shrink the YAxis. var labelYMaxRequired = (text.Location.Y - labelHeight * YAxis.Scale.Min / axisHeight) / (1 - labelHeight / axisHeight); yMaxRequired = Math.Max(yMaxRequired, labelYMaxRequired); } } if (!GraphObjList.Any( o => (o is TextObj) && ((TextObj)o).Location == text.Location && ((TextObj)o).Text == text.Text)) { if (_pointAnnotations.Contains(text)) { GraphObjList.Add(text); } } } if (maxAuto && yMaxRequired > 0) { yAxis.Scale.Max = Math.Max(yAxis.Scale.Max, yMaxRequired); } } finally { // Reset the value of MaxAuto since it may have been changed to false when Scale.Max was changed. yAxis.Scale.MaxAuto = maxAuto; } }
private void drawLabels(Graphics g) { foreach (GraphObj pa in _pointAnnotations) { GraphObjList.Remove(pa); } _pointAnnotations.Clear(); _manualLabels.Clear(); Axis xAxis = XAxis; Axis yAxis = YAxis; yAxis.Scale.MinAuto = false; if (LockYAxisAtZero) { yAxis.Scale.Min = 0; } // ensure that the chart rectangle is the right size AxisChange(g); // then setup axes scales to enable the Transform method xAxis.Scale.SetupScaleData(this, xAxis); yAxis.Scale.SetupScaleData(this, yAxis); if (Chart.Rect.Width < 1 || Chart.Rect.Height < 1) { return; } _overlapDetector = AllowLabelOverlap ? null : new OverlapDetector(); Region chartRegion = new Region(Chart.Rect); Region clipRegion = new Region(); clipRegion.MakeEmpty(); var previousClip = g.Clip.Clone(); g.SetClip(Rect, CombineMode.Replace); g.SetClip(chartRegion, CombineMode.Exclude); /*Bitmap clipBmp = new Bitmap(Convert.ToInt32(Chart.Rect.Width), Convert.ToInt32(Chart.Rect.Height)); * Graphics clipG = Graphics.FromImage(clipBmp); * clipG.Clear(Color.White); * clipG.FillRegion(new SolidBrush(Color.Black), g.Clip); * clipBmp.Save("C:\\clip.bmp");*/ // some dummy labels for very fast clipping string baseLabel = "0"; // Not L10N foreach (CurveItem item in CurveList) { IMSGraphItemInfo info = item.Tag as IMSGraphItemInfo; if (info != null) { PointAnnotation annotation = info.AnnotatePoint(new PointPair(0, 0)); if (annotation != null && annotation.Label != null && annotation.Label.Length > baseLabel.Length) { baseLabel = annotation.Label; } } } TextObj baseTextObj = new TextObj(baseLabel, 0, 0); baseTextObj.FontSpec.Border.IsVisible = false; baseTextObj.FontSpec.Fill.IsVisible = false; PointF[] pts = baseTextObj.FontSpec.GetBox(g, baseLabel, 0, 0, AlignH.Center, AlignV.Bottom, 1.0f, new SizeF()); float baseLabelWidth = pts[1].X - pts[0].X; float baseLabelHeight = pts[2].Y - pts[0].Y; baseLabelWidth = (float)xAxis.Scale.ReverseTransform(xAxis.Scale.Transform(0) + baseLabelWidth); baseLabelHeight = (float)yAxis.Scale.ReverseTransform(yAxis.Scale.Transform(0) - baseLabelHeight); float labelLengthToWidthRatio = baseLabelWidth / baseLabel.Length; float xAxisPixel = yAxis.Scale.Transform(0); double xMin = xAxis.Scale.Min; double xMax = xAxis.Scale.Max; double yMin = yAxis.Scale.Min; double yMax = yAxis.Scale.Max; // add manual annotations with TextObj priority over curve annotations foreach (CurveItem item in CurveList) { var info = item.Tag as IMSGraphItemExtended; MSPointList points = item.Points as MSPointList; if (info == null || points == null) { continue; } info.AddPreCurveAnnotations(this, g, points, _pointAnnotations); AddAnnotations(g); } // add automatic labels for MSGraphItems foreach (CurveItem item in CurveList) { IMSGraphItemInfo info = item.Tag as IMSGraphItemInfo; MSPointList points = item.Points as MSPointList; if (info == null || points == null) { continue; } if (info.ToString().Length == 0) { continue; } PointPairList fullList = points.FullList; List <int> maxIndexList = points.ScaledMaxIndexList; var annotationsPrioritized = new Dictionary <PointAnnotation, int>(); for (int i = 0; i < maxIndexList.Count; ++i) { if (maxIndexList[i] < 0) { continue; } PointPair pt = fullList[maxIndexList[i]]; if (pt.X < xMin || pt.Y > yMax || pt.Y < yMin) { continue; } if (pt.X > xMax) { break; } float yPixel = yAxis.Scale.Transform(pt.Y); // labelled points must be at least 3 pixels off the X axis if (xAxisPixel - yPixel < 3) { continue; } PointAnnotation annotation = info.AnnotatePoint(pt); if (annotation != null) { annotationsPrioritized.Add(annotation, i); } } // Give the higher ranked point priority foreach (var annotation in annotationsPrioritized.Keys.OrderBy(a => a.ZOrder ?? int.MaxValue)) { if (annotation.ExtraAnnotation != null) { GraphObjList.Add(annotation.ExtraAnnotation); _pointAnnotations.Add(annotation.ExtraAnnotation); } if (string.IsNullOrEmpty(annotation.Label)) { continue; } float pointLabelWidth = labelLengthToWidthRatio * annotation.Label.Split('\n').Max(o => o.Length); var i = annotationsPrioritized[annotation]; PointPair pt = fullList[maxIndexList[i]]; float yPixel = yAxis.Scale.Transform(pt.Y); double labelY = yAxis.Scale.ReverseTransform(yPixel - 5); if (!AllowCurveOverlap) { // do fast check for overlap against all MSGraphItems bool overlap = false; foreach (CurveItem item2 in CurveList) { MSPointList points2 = item2.Points as MSPointList; if (points2 != null) { int nearestMaxIndex = points2.GetNearestMaxIndexToBin(i); if (nearestMaxIndex < 0) { continue; } RectangleF r = new RectangleF((float)pt.X - pointLabelWidth / 2, (float)labelY - baseLabelHeight, pointLabelWidth, baseLabelHeight); overlap = detectLabelCurveOverlap(this, points2.FullList, nearestMaxIndex, item2 is StickItem, r); if (overlap) { break; } } } if (overlap) { continue; } } TextObj text = new TextObj(annotation.Label, pt.X, labelY, CoordType.AxisXYScale, AlignH.Center, AlignV.Bottom) { ZOrder = ZOrder.A_InFront, FontSpec = annotation.FontSpec, IsClippedToChartRect = true }; var textRect = _labelBoundsCache.GetLabelBounds(text, this, g); bool overlap2 = _overlapDetector != null && _overlapDetector.Overlaps(textRect); _manualLabels[text] = textRect; if (!overlap2) { _pointAnnotations.Add(text); AddAnnotations(g); } } } // add manual annotations foreach (CurveItem item in CurveList) { IMSGraphItemInfo info = item.Tag as IMSGraphItemInfo; MSPointList points = item.Points as MSPointList; if (info == null || points == null) { continue; } info.AddAnnotations(this, g, points, _pointAnnotations); AddAnnotations(g); } autoScaleForManualLabels(g); g.Clip = previousClip; }
private void drawLabels(Graphics g) { foreach (GraphObj pa in _pointAnnotations) { GraphObjList.Remove(pa); } _pointAnnotations.Clear(); Axis xAxis = XAxis; Axis yAxis = YAxis; yAxis.Scale.MinAuto = false; yAxis.Scale.Min = 0; // setup axes scales to enable the Transform method xAxis.Scale.SetupScaleData(this, xAxis); yAxis.Scale.SetupScaleData(this, yAxis); if (Chart.Rect.Width < 1 || Chart.Rect.Height < 1) { return; } Region textBoundsRegion; Region chartRegion = new Region(Chart.Rect); Region clipRegion = new Region(); clipRegion.MakeEmpty(); g.SetClip(Rect, CombineMode.Replace); g.SetClip(chartRegion, CombineMode.Exclude); /*Bitmap clipBmp = new Bitmap(Convert.ToInt32(Chart.Rect.Width), Convert.ToInt32(Chart.Rect.Height)); * Graphics clipG = Graphics.FromImage(clipBmp); * clipG.Clear(Color.White); * clipG.FillRegion(new SolidBrush(Color.Black), g.Clip); * clipBmp.Save("C:\\clip.bmp");*/ // some dummy labels for very fast clipping string baseLabel = "0"; foreach (CurveItem item in CurveList) { IMSGraphItemInfo info = item.Tag as IMSGraphItemInfo; if (info != null) { PointAnnotation annotation = info.AnnotatePoint(new PointPair(0, 0)); if (annotation != null && annotation.Label != null && annotation.Label.Length > baseLabel.Length) { baseLabel = annotation.Label; } } } TextObj baseTextObj = new TextObj(baseLabel, 0, 0); baseTextObj.FontSpec.Border.IsVisible = false; baseTextObj.FontSpec.Fill.IsVisible = false; PointF[] pts = baseTextObj.FontSpec.GetBox(g, baseLabel, 0, 0, AlignH.Center, AlignV.Bottom, 1.0f, new SizeF()); float baseLabelWidth = (float)Math.Round(pts[1].X - pts[0].X); float baseLabelHeight = (float)Math.Round(pts[2].Y - pts[0].Y); baseLabelWidth = (float)xAxis.Scale.ReverseTransform(xAxis.Scale.Transform(0) + baseLabelWidth); baseLabelHeight = (float)yAxis.Scale.ReverseTransform(yAxis.Scale.Transform(0) - baseLabelHeight); float labelLengthToWidthRatio = baseLabelWidth / baseLabel.Length; float xAxisPixel = yAxis.Scale.Transform(0); double xMin = xAxis.Scale.Min; double xMax = xAxis.Scale.Max; double yMin = yAxis.Scale.Min; double yMax = yAxis.Scale.Max; // add automatic labels for MSGraphItems foreach (CurveItem item in CurveList) { IMSGraphItemInfo info = item.Tag as IMSGraphItemInfo; MSPointList points = item.Points as MSPointList; if (info == null || points == null) { continue; } if (info.ToString().Length == 0) { continue; } PointPairList fullList = points.FullList; List <int> maxIndexList = points.ScaledMaxIndexList; for (int i = 0; i < maxIndexList.Count; ++i) { if (maxIndexList[i] < 0) { continue; } PointPair pt = fullList[maxIndexList[i]]; if (pt.X < xMin || pt.Y > yMax || pt.Y < yMin) { continue; } if (pt.X > xMax) { break; } float yPixel = yAxis.Scale.Transform(pt.Y); // labelled points must be at least 3 pixels off the X axis if (xAxisPixel - yPixel < 3) { continue; } PointAnnotation annotation = info.AnnotatePoint(pt); if (annotation == null) { continue; } if (annotation.ExtraAnnotation != null) { GraphObjList.Add(annotation.ExtraAnnotation); _pointAnnotations.Add(annotation.ExtraAnnotation); } if (string.IsNullOrEmpty(annotation.Label)) { continue; } float pointLabelWidth = labelLengthToWidthRatio * annotation.Label.Length; double labelY = yAxis.Scale.ReverseTransform(yPixel - 5); if (!AllowCurveOverlap) { // do fast check for overlap against all MSGraphItems bool overlap = false; foreach (CurveItem item2 in CurveList) { MSPointList points2 = item2.Points as MSPointList; if (points2 != null) { int nearestMaxIndex = points2.GetNearestMaxIndexToBin(i); if (nearestMaxIndex < 0) { continue; } RectangleF r = new RectangleF((float)pt.X - pointLabelWidth / 2, (float)labelY - baseLabelHeight, pointLabelWidth, baseLabelHeight); overlap = detectLabelCurveOverlap(this, points2.FullList, nearestMaxIndex, item2 is StickItem, r); if (overlap) { break; } } } if (overlap) { continue; } } TextObj text = new TextObj(annotation.Label, pt.X, labelY, CoordType.AxisXYScale, AlignH.Center, AlignV.Bottom) { ZOrder = ZOrder.A_InFront, FontSpec = annotation.FontSpec }; //text.IsClippedToChartRect = true; if (!detectLabelOverlap(this, g, text, out textBoundsRegion, item.Points, maxIndexList[i], item is StickItem)) { GraphObjList.Add(text); _pointAnnotations.Add(text); clipRegion.Union(textBoundsRegion); g.SetClip(clipRegion, CombineMode.Replace); } } } // add manual annotations foreach (CurveItem item in CurveList) { IMSGraphItemInfo info = item.Tag as IMSGraphItemInfo; MSPointList points = item.Points as MSPointList; if (info == null || points == null) { continue; } info.AddAnnotations(this, g, points, _pointAnnotations); foreach (GraphObj obj in _pointAnnotations) { if (!GraphObjList.Contains(obj)) { TextObj text = obj as TextObj; if (text != null) { if (detectLabelOverlap(this, g, text, out textBoundsRegion, item.Points, -1, item is StickItem)) { continue; } clipRegion.Union(textBoundsRegion); g.SetClip(clipRegion, CombineMode.Replace); } GraphObjList.Add(obj); } } /*GraphObjList objsToRemove = new GraphObjList(); * foreach( GraphObj obj in GraphObjList ) * if( !pointAnnotations_.Contains( obj ) ) * objsToRemove.Add( obj ); * foreach( GraphObj obj in objsToRemove ) * GraphObjList.Remove( obj );*/ } }
public override void UpdateGraph(bool selectionChanged) { CurveList.Clear(); GraphObjList.Clear(); SrmDocument document = GraphSummary.DocumentUIContainer.DocumentUI; var selectedTreeNode = GraphSummary.StateProvider.SelectedNode as SrmTreeNode; if (selectedTreeNode == null || document.FindNode(selectedTreeNode.Path) == null) { Title.Text = Helpers.PeptideToMoleculeTextMapper.Translate(Resources.MassErrorReplicateGraphPane_UpdateGraph_Select_a_peptide_to_see_the_mass_error_graph, document.DocumentType); EmptyGraph(document); return; } if (!document.Settings.HasResults) { Title.Text = Resources.AreaReplicateGraphPane_UpdateGraph_No_results_available; EmptyGraph(document); return; } 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); } Title.Text = null; var aggregateOp = GraphValues.AggregateOp.FromCurrentSettings(); YAxis.Title.Text = aggregateOp.Cv ? aggregateOp.AnnotateTitle(Resources.MassErrorReplicateGraphPane_UpdateGraph_Mass_Error_No_Ppm) : Resources.MassErrorReplicateGraphPane_UpdateGraph_Mass_Error; DocNode selectedNode = selectedTreeNode.Model; DocNode parentNode = selectedNode; IdentityPath identityPath = selectedTreeNode.Path; // If the selected tree node is a transition, then its siblings are displayed. if (selectedTreeNode is TransitionTreeNode) { if (displayType != DisplayTypeChrom.single) { 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 if (!(selectedTreeNode is TransitionGroupTreeNode)) { Title.Text = Helpers.PeptideToMoleculeTextMapper.Translate(Resources.MassErrorReplicateGraphPane_UpdateGraph_Select_a_peptide_to_see_the_mass_error_graph, document.DocumentType); EmptyGraph(document); CanShowMassErrorLegend = false; return; } // If a precursor is going to be displayed with display type single if (parentNode is TransitionGroupDocNode && displayType == DisplayTypeChrom.single) { // If no optimization data, then show all the transitions displayType = DisplayTypeChrom.all; } var replicateGroupOp = ReplicateGroupOp.FromCurrentSettings(document.Settings); GraphData graphData = new MassErrorGraphData(document, identityPath, displayType, replicateGroupOp, PaneKey); CanShowMassErrorLegend = graphData.DocNodes.Count != 0; InitFromData(graphData); int selectedReplicateIndex = SelectedIndex; double minRetentionTime = double.MaxValue; double maxRetentionTime = double.MinValue; int iColor = 0, iCharge = -1; var charge = Adduct.EMPTY; int countLabelTypes = document.Settings.PeptideSettings.Modifications.CountLabelTypes; int colorOffset = 0; var transitionGroupDocNode = parentNode as TransitionGroupDocNode; if (transitionGroupDocNode != null && displayType == DisplayTypeChrom.products) { // If we are only displaying product ions, we want to use an offset in the colors array // so that we do not re-use colors that would be used for any precursor ions. colorOffset = GraphChromatogram.GetDisplayTransitions(transitionGroupDocNode, DisplayTypeChrom.precursors).Count(); } for (int i = 0; i < graphData.DocNodes.Count; 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; // ReSharper disable ExpressionIsAlwaysNull var nodeGroup = docNode as TransitionGroupDocNode; if (parentNode is PeptideDocNode) { int iColorGroup = GetColorIndex(nodeGroup, countLabelTypes, ref charge, ref iCharge); color = COLORS_GROUPS[iColorGroup % COLORS_GROUPS.Count]; } else if (displayType == DisplayTypeChrom.total) { color = COLORS_GROUPS[iColor % COLORS_GROUPS.Count]; } else if (docNode.Equals(selectedNode) && step == 0) { color = ChromGraphItem.ColorSelected; } else { color = COLORS_TRANSITION[(iColor + colorOffset) % COLORS_TRANSITION.Count]; } // ReSharper restore ExpressionIsAlwaysNull iColor++; string label = graphData.DocNodeLabels[i]; if (step != 0) { label = string.Format(Resources.RTReplicateGraphPane_UpdateGraph_Step__0__, step); } BarItem curveItem = new MeanErrorBarItem(label, pointPairList, color, Color.Black); if (selectedReplicateIndex != -1 && selectedReplicateIndex < pointPairList.Count) { PointPair pointPair = pointPairList[selectedReplicateIndex]; if (!pointPair.IsInvalid) { minRetentionTime = Math.Min(minRetentionTime, pointPair.Y); maxRetentionTime = Math.Max(maxRetentionTime, pointPair.Y); } } curveItem.Bar.Border.IsVisible = false; curveItem.Bar.Fill.Brush = new SolidBrush(color); curveItem.Tag = new IdentityPath(identityPath, docNode.Id); CurveList.Add(curveItem); } } // Draw a box around the currently selected replicate if (ShowSelection && minRetentionTime != double.MaxValue) { maxRetentionTime = Math.Max(maxRetentionTime, 0); minRetentionTime = Math.Min(minRetentionTime, 0); GraphObjList.Add(new BoxObj(selectedReplicateIndex + .5, maxRetentionTime, 1, maxRetentionTime - minRetentionTime, Color.Black, Color.Empty) { IsClippedToChartRect = true, }); } XAxis.Scale.MinAuto = XAxis.Scale.MaxAuto = selectionChanged; YAxis.Scale.MinAuto = YAxis.Scale.MaxAuto = true; if (Settings.Default.MinMassError != 0) { YAxis.Scale.Min = Settings.Default.MinMassError; } if (Settings.Default.MaxMassError != 0) { YAxis.Scale.Max = Settings.Default.MaxMassError; } Legend.IsVisible = Settings.Default.ShowMassErrorLegend; 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) { SrmDocument document = GraphSummary.DocumentUIContainer.DocumentUI; var results = document.Settings.MeasuredResults; bool resultsAvailable = results != null; Clear(); if (!resultsAvailable) { Title.Text = Resources.RTReplicateGraphPane_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; } Title.Text = null; DisplayTypeChrom displayType = GraphChromatogram.GetDisplayType(document, selectedTreeNode); DocNode selectedNode = selectedTreeNode.Model; DocNode parentNode = selectedNode; IdentityPath identityPath = selectedTreeNode.Path; // If the selected tree node is a transition, then its siblings are displayed. if (selectedTreeNode is TransitionTreeNode) { if (displayType != DisplayTypeChrom.single) { 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 = ((DocNodeParent)selectedNode).Children; if (children.Count == 1 && displayType != DisplayTypeChrom.total) { selectedNode = parentNode = children[0]; identityPath = new IdentityPath(identityPath, parentNode.Id); } } else if (!(selectedTreeNode is TransitionGroupTreeNode)) { Title.Text = Resources.RTReplicateGraphPane_UpdateGraph_Select_a_peptide_to_see_the_retention_time_graph; CanShowRTLegend = false; return; } // If a precursor is going to be displayed with display type single if (parentNode is TransitionGroupDocNode && displayType == DisplayTypeChrom.single) { // If no optimization data, then show all the transitions if (!results.Chromatograms.Contains(chrom => chrom.OptimizationFunction != null)) { displayType = DisplayTypeChrom.all; } } var rtTransformOp = GraphSummary.StateProvider.GetRetentionTimeTransformOperation(); var rtValue = RTPeptideGraphPane.RTValue; GraphValues.ReplicateGroupOp replicateGroupOp; if (rtValue == RTPeptideValue.All) { replicateGroupOp = GraphValues.ReplicateGroupOp.FromCurrentSettings(document.Settings, GraphValues.AggregateOp.MEAN); } else { replicateGroupOp = GraphValues.ReplicateGroupOp.FromCurrentSettings(document.Settings); } var retentionTimeValue = new GraphValues.RetentionTimeTransform(rtValue, rtTransformOp, replicateGroupOp.AggregateOp); YAxis.Title.Text = retentionTimeValue.GetAxisTitle(); GraphData graphData = new RTGraphData(document, parentNode, displayType, retentionTimeValue, replicateGroupOp); CanShowRTLegend = graphData.DocNodes.Count != 0; InitFromData(graphData); int selectedReplicateIndex = SelectedIndex; double minRetentionTime = double.MaxValue; double maxRetentionTime = -double.MaxValue; int iColor = 0, iCharge = -1; int? charge = null; int countLabelTypes = document.Settings.PeptideSettings.Modifications.CountLabelTypes; int colorOffset = 0; var transitionGroupDocNode = parentNode as TransitionGroupDocNode; if (transitionGroupDocNode != null && displayType == DisplayTypeChrom.products) { // If we are only displaying product ions, we want to use an offset in the colors array // so that we do not re-use colors that would be used for any precursor ions. colorOffset = GraphChromatogram.GetDisplayTransitions(transitionGroupDocNode, DisplayTypeChrom.precursors).Count(); } for (int i = 0; i < graphData.DocNodes.Count; 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) { // Resharper code inspection v9.0 on TC gets this one wrong // ReSharper disable ExpressionIsAlwaysNull int iColorGroup = GetColorIndex(nodeGroup, countLabelTypes, ref charge, ref iCharge); // ReSharper restore ExpressionIsAlwaysNull 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++; string label = graphData.DocNodeLabels[i]; if (step != 0) { label = string.Format(Resources.RTReplicateGraphPane_UpdateGraph_Step__0__, step); } BarItem curveItem; if (HiLowMiddleErrorBarItem.IsHiLoMiddleErrorList(pointPairList)) { curveItem = new HiLowMiddleErrorBarItem(label, pointPairList, color, Color.Black); } else { curveItem = new MeanErrorBarItem(label, pointPairList, color, Color.Black); } if (selectedReplicateIndex != -1 && selectedReplicateIndex < pointPairList.Count) { PointPair pointPair = pointPairList[selectedReplicateIndex]; if (!pointPair.IsInvalid) { minRetentionTime = Math.Min(minRetentionTime, pointPair.Z); maxRetentionTime = Math.Max(maxRetentionTime, pointPair.Y); } } curveItem.Bar.Border.IsVisible = false; curveItem.Bar.Fill.Brush = new SolidBrush(color); curveItem.Tag = new IdentityPath(identityPath, docNode.Id); CurveList.Add(curveItem); } } // Draw a box around the currently selected replicate if (ShowSelection && minRetentionTime != double.MaxValue) { GraphObjList.Add(new BoxObj(selectedReplicateIndex + .5, maxRetentionTime, 1, maxRetentionTime - minRetentionTime, Color.Black, Color.Empty) { IsClippedToChartRect = true, }); } // Reset the scale when the parent node changes if (_parentNode == null || !ReferenceEquals(_parentNode.Id, parentNode.Id)) { XAxis.Scale.MaxAuto = XAxis.Scale.MinAuto = true; YAxis.Scale.MaxAuto = YAxis.Scale.MinAuto = true; } _parentNode = parentNode; Legend.IsVisible = Settings.Default.ShowRetentionTimesLegend; AxisChange(); }
public override void AddAnnotations(MSGraphPane graphPane, Graphics g, MSPointList pointList, GraphObjList annotations) { if (Chromatogram == null) { return; } // Calculate maximum y for potential retention time indicators PointF ptTop = new PointF(0, graphPane.Chart.Rect.Top); if (GraphChromatogram.ShowRT != ShowRTChrom.none) { if (RetentionMsMs != null) { foreach (double retentionTime in RetentionMsMs) { Color color = COLOR_MSMSID_TIME; if (SelectedRetentionMsMs.HasValue && Equals((float)retentionTime, (float)SelectedRetentionMsMs)) { color = ColorSelected; } AddRetentionTimeAnnotation(graphPane, g, annotations, ptTop, Resources.ChromGraphItem_AddAnnotations_ID, GraphObjType.ms_ms_id, color, ScaleRetentionTime(retentionTime)); } } if (MidasRetentionMsMs != null) { foreach (var retentionTime in MidasRetentionMsMs) { var color = SelectedRetentionMsMs.HasValue && Equals((float)retentionTime, (float)SelectedRetentionMsMs) ? ColorSelected : COLOR_MSMSID_TIME; AddRetentionTimeAnnotation(graphPane, g, annotations, ptTop, string.Empty, GraphObjType.midas_spectrum, color, ScaleRetentionTime(retentionTime)); } } if (AlignedRetentionMsMs != null) { foreach (var time in AlignedRetentionMsMs) { var scaledTime = ScaleRetentionTime(time); var line = new LineObj(COLOR_ALIGNED_MSMSID_TIME, scaledTime.DisplayTime, 0, scaledTime.DisplayTime, 1) { ZOrder = ZOrder.F_BehindGrid, Location = { CoordinateFrame = CoordType.XScaleYChartFraction }, IsClippedToChartRect = true, Tag = new GraphObjTag(this, GraphObjType.aligned_ms_id, scaledTime), }; annotations.Add(line); } } if (UnalignedRetentionMsMs != null) { foreach (var time in UnalignedRetentionMsMs) { var scaledTime = ScaleRetentionTime(time); var line = new LineObj(COLOR_UNALIGNED_MSMSID_TIME, scaledTime.DisplayTime, 0, scaledTime.DisplayTime, 1) { ZOrder = ZOrder.F_BehindGrid, Location = { CoordinateFrame = CoordType.XScaleYChartFraction }, IsClippedToChartRect = true, Tag = new GraphObjTag(this, GraphObjType.unaligned_ms_id, scaledTime), }; annotations.Add(line); } } } // Draw retention time indicator, if set if (RetentionPrediction.HasValue) { double time = RetentionPrediction.Value; // Create temporary label to calculate positions if (GraphChromatogram.ShowRT != ShowRTChrom.none) { AddRetentionTimeAnnotation(graphPane, g, annotations, ptTop, Resources.ChromGraphItem_AddAnnotations_Predicted, GraphObjType.predicted_rt_window, COLOR_RETENTION_TIME, ScaleRetentionTime(time)); } // Draw background for retention time window if (RetentionWindow > 0) { double x1 = ScaleRetentionTime(time - RetentionWindow / 2).DisplayTime; double x2 = ScaleRetentionTime(time + RetentionWindow / 2).DisplayTime; BoxObj box = new BoxObj(x1, 0, x2 - x1, 1, COLOR_RETENTION_WINDOW, COLOR_RETENTION_WINDOW) { Location = { CoordinateFrame = CoordType.XScaleYChartFraction }, IsClippedToChartRect = true, ZOrder = ZOrder.F_BehindGrid }; annotations.Add(box); } } if (RetentionExplicit != null && GraphChromatogram.ShowRT != ShowRTChrom.none) { // Create temporary label to calculate positions AddRetentionTimeAnnotation(graphPane, g, annotations, ptTop, Resources.ChromGraphItem_AddAnnotations_Explicit, GraphObjType.predicted_rt_window, COLOR_RETENTION_TIME, ScaleRetentionTime(RetentionExplicit.RetentionTime)); } for (int i = 0, len = Chromatogram.NumPeaks; i < len; i++) { if (_arrayLabelIndexes[i] == -1) { continue; } double maxIntensity = _intensities[_arrayLabelIndexes[i]]; // Show peak extent indicators, if they are far enough apart ChromPeak peak = Chromatogram.GetPeak(i); AddPeakBoundaries(graphPane, annotations, false, ScaleRetentionTime(peak.StartTime), ScaleRetentionTime(peak.EndTime), maxIntensity); } }
public void doPlot(IEnumerable <Position> positions) { clear(); var closed = O.accept(positions, position => position.isClosed()); var pnls = O.sort(O.convert(closed, toValue)); var min = O.first(pnls); var max = O.last(pnls); var range = max - min; var bucketCount = Math.Max(Math.Min(150, pnls.Count / 5), 1); var blockSize = Math.Max(1, range / bucketCount); if (blockSize == 1) { bucketCount = (int)range + 1; } var buckets = O.array(O.nCopies(bucketCount, 0.0)); O.each(pnls, pnl => { var bucket = (int)((pnl - min) / blockSize); if (bucket == bucketCount) { bucket--; } buckets[bucket]++; }); var bucketStarts = O.array(O.convert(buckets, (i, unused) => i * blockSize + min)); var pnlCount = O.count(pnls); var lowerQuartile = pnls[pnlCount / 4]; var upperQuartile = pnls[3 * pnlCount / 4]; var median = pnls[pnlCount / 2]; var mean = O.average(pnls); var sd = O.populationStandardDeviation(pnls); var colors = O.array(O.convert(bucketStarts, (i, bucket) => { var isLow = bucket < median; var isBright = bucket <= lowerQuartile || bucket >= upperQuartile; if (isLow) { return(isBright ? (2.0 / 3.0) : 0.0); } return(isBright ? 1.0 : (1.0 / 3.0)); })); var points = new PointPairList(bucketStarts, buckets, colors); addBars("pnls", O.array(Color.DarkRed, Color.FromArgb(0, 18, 110), Color.Red, Color.FromArgb(0, 60, 255)), points); GraphObjList.Add(new LineObj(Color.Lime, 0, 0, 0, 1) { Location = { CoordinateFrame = CoordType.XScaleYChartFraction }, Line = { Style = DashStyle.Dot, Width = 2 } }); GraphObjList.Add(new TextObj(O.join("\n", O.list( "min = " + O.prettyNumber(min), "25% = " + O.prettyNumber(lowerQuartile), "50% = " + O.prettyNumber(median), "75% = " + O.prettyNumber(upperQuartile), "max = " + O.prettyNumber(max), "", "mean = " + O.prettyNumber(mean), "sd(pop) = " + O.prettyNumber(sd) )), 0.9, 0.12, CoordType.ChartFraction) { FontSpec = { StringAlignment = StringAlignment.Near } }); BarSettings.MinClusterGap = 0; XAxis.Scale.MinGrace = 0; XAxis.Scale.MaxGrace = 0; }
public override void UpdateGraph(bool selectionChanged) { GraphObjList.Clear(); CurveList.Clear(); Legend.IsVisible = false; if (!DetectionPlotData.GetDataCache().TryGet( GraphSummary.DocumentUIContainer.DocumentUI, Settings.QValueCutoff, this.DataCallback, out _detectionData)) { return; } AddLabels(); BarSettings.Type = BarType.SortedOverlay; BarSettings.MinClusterGap = 0.3f; Legend.IsVisible = Settings.ShowLegend; var emptySymbol = new Symbol(SymbolType.None, Color.Transparent); //draw bars var counts = TargetData.TargetsCount; var countPoints = new PointPairList(Enumerable.Range(0, _detectionData.ReplicateCount) .Select(i => new PointPair(i, counts[i] / YScale)).ToList()); CurveList.Insert(0, MakeBarItem(countPoints, Color.FromArgb(180, 220, 255))); //draw cumulative curve counts = TargetData.TargetsCumulative; var cumulativePoints = new PointPairList(Enumerable.Range(0, _detectionData.ReplicateCount) .Select(i => new PointPair(i, counts[i] / YScale)).ToList()); CurveList.Insert(1, new LineItem(Resources.DetectionPlotPane_CumulativeLine_Name) { Points = cumulativePoints, Symbol = emptySymbol, Line = new Line() { Color = Color.Coral, Width = 2 } }); //draw inclusive curve counts = TargetData.TargetsAll; var allPoints = new PointPairList(Enumerable.Range(0, _detectionData.ReplicateCount) .Select(i => new PointPair(i, counts[i] / YScale)).ToList()); CurveList.Insert(2, new LineItem(Resources.DetectionPlotPane_AllRunsLine_Name) { Symbol = emptySymbol, Points = allPoints, Line = new Line() { Color = Color.Black, Width = 2 } }); //axes formatting XAxis.Scale.Max = _detectionData.ReplicateCount + 1; YAxis.Scale.Max = _detectionData.GetTargetData(Settings.TargetType).MaxCount / YScale * 1.15; if (Settings.ShowAtLeastN) { double lineY = TargetData.getCountForMinReplicates(Settings.RepCount); var atLeastLine = new Line() { Width = 1, Color = Color.Blue, Style = DashStyle.Dash }; var dummyPoints = new PointPairList(new[] { new PointPair(0, 0) }); var line = new LineObj(Color.Blue, 0, lineY / YScale, XAxis.Scale.Max, lineY / YScale) { IsClippedToChartRect = true, Line = atLeastLine }; GraphObjList.Add(line); //This is a placeholder to make sure the line shows in the legend. CurveList.Insert(3, new LineItem(String.Format(CultureInfo.CurrentCulture, Resources.DetectionPlotPane_AtLeastLine_Name, Settings.RepCount, _detectionData.ReplicateCount, lineY)) { Symbol = emptySymbol, Points = dummyPoints, Line = atLeastLine }); } if (Settings.ShowSelection) { var selectedIndex = GraphSummary.StateProvider.SelectedResultsIndex; var lineLength = TargetData.TargetsCount[selectedIndex] / YScale + YAxis.Scale.Max * 0.05; GraphObjList.Add( new LineObj(Color.Black, selectedIndex + 1, 0, selectedIndex + 1, lineLength) { IsClippedToChartRect = true, Line = new Line() { Width = 1, Color = Color.Black, Style = DashStyle.Dash } }); } if (Settings.ShowMean) { var stats = new Statistics(TargetData.TargetsCount.Select((x) => (double)x)); var labelText = String.Format(CultureInfo.CurrentCulture, TextUtil.LineSeparate(new[] { Resources.DetectionPlotPane_Label_Mean, Resources.DetectionPlotPane_Label_Stddev } ), stats.Mean(), stats.StdDev()); GraphObjList.Add(new TextObj(labelText, 0.1, YAxis.Scale.Max, CoordType.AxisXYScale, AlignH.Left, AlignV.Top) { IsClippedToChartRect = true, ZOrder = ZOrder.E_BehindCurves, FontSpec = GraphSummary.CreateFontSpec(Color.Black), }); } }
/// <summary> /// Highlight the interiorPos position of selected planets or averages. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void timer1_Tick(object sender, EventArgs e) { if (currentIndicators.Count != 0) { foreach (GraphObj obj in currentIndicators) { zedLongTerm.GraphPane.GraphObjList.Remove(obj); } currentIndicators.Clear(); } #region Draw the line to highlight interiorPos planet positions DateTimeOffset now = DateTimeOffset.UtcNow; string timeString = DateTimeOffset.Now.ToString("MM-dd HH:mm"); now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, TimeSpan.Zero); double x = now.DateTime.ToOADate(); LineObj nowIndicator = new LineObj(x, zedLongTerm.GraphPane.YAxis.Scale.Min - 10, x, zedLongTerm.GraphPane.YAxis.Scale.Max + 10); nowIndicator.Line.Style = System.Drawing.Drawing2D.DashStyle.Dash; nowIndicator.Line.Color = Color.Gray; currentIndicators.Add(nowIndicator); #region With the lable of local time under the line TextObj timeIndicator = new TextObj(timeString, x, 0, CoordType.AxisXYScale); timeIndicator.Location.AlignH = AlignH.Center; timeIndicator.Location.AlignV = AlignV.Top; timeIndicator.FontSpec.Fill.Color = Color.Yellow; timeIndicator.FontSpec.Fill.IsVisible = true; timeIndicator.FontSpec.Border.IsVisible = true; timeIndicator.FontSpec.Size = 6f; currentIndicators.Add(timeIndicator); #endregion if (checkBoxReadings.Checked) { for (int i = 0; i < CurrentEphemeris.Luminaries.Count; i++) { CheckBox cb = panelStars.Controls[i] as CheckBox; Position pos = null; if (cb != null && cb.Checked) { PlanetId id = CurrentEphemeris.Luminaries[i]; string label = null; double y = 180; if (id < PlanetId.SE_FICT_OFFSET) { pos = CurrentEphemeris[now, id]; y = pos.Longitude; label = string.Format("{0}: {1} ({2})", Planet.Glyphs[id], pos.Longitude.ToString("F1"), Rectascension.AstroStringOf(pos.Longitude)); } else if (OrbitsDict[PositionValueIndex.Longitude].ContainsKey(id)) { int todayIndex = (int)Math.Floor(x - since.DateTime.ToOADate()); double y1 = OrbitsDict[PositionValueIndex.Longitude][id][todayIndex]; double y2 = OrbitsDict[PositionValueIndex.Longitude][id][todayIndex + 1]; y = y1 + (y2 - y1) / (x - since.DateTime.ToOADate()); label = string.Format("{0}: {1:F1} ({2})", Planet.Glyphs[id], y, Rectascension.AstroStringOf(y)); } TextObj posText = lableOf(label, x, y); posText.Location.AlignV = y < 180 ? AlignV.Bottom : AlignV.Top; currentIndicators.Add(posText); } } } #endregion foreach (GraphObj obj in currentIndicators) { zedLongTerm.GraphPane.GraphObjList.Add(obj); } zedLongTerm.Invalidate(); }
public void add(List <Position> positions, List <Trade> trades, Simulator simulator) { Action <Trade, double> addTrade = (trade, x) => { var y = trade.price; var color = trade.direction.longShort(Color.Green, Color.Red); var line = AddCurve("", new PointPairList { { x, y } }, color, SymbolType.Circle); line.Symbol.Fill = new Fill(color); line.Label.IsVisible = false; line.Line.IsVisible = false; line.IsOverrideOrdinal = true; var arrow = new ArrowObj(x, trade.direction.longShort(0.93, 0.07), x, trade.direction.longShort(0.89, 0.11)) { Location = { CoordinateFrame = CoordType.XScaleYChartFraction }, ZOrder = ZOrder.A_InFront }; GraphObjList.Add(arrow); var dottedLine = new LineObj(Color.LightGray, x, 0.11, x, 0.89) { ZOrder = ZOrder.E_BehindCurves, Line = { Style = DashStyle.Dot }, Location = { CoordinateFrame = CoordType.XScaleYChartFraction } }; GraphObjList.Add(dottedLine); var text = new TextObj( trade.description + "\n" + trade.size + "@" + trade.price.ToString("n4"), x, trade.direction.longShort(0.935, 0.065), CoordType.XScaleYChartFraction, AlignH.Center, trade.direction.longShort(AlignV.Top, AlignV.Bottom) ) { FontSpec = { Size = 8, Border = { IsVisible = false } } }; if (Objects.username().Equals("rsheftel")) { text.FontSpec.FontColor = Color.Fuchsia; text.FontSpec.Size = 11; } GraphObjList.Add(text); }; Objects.each(trades, trade => addTrade(trade, dateParent.index(trade.time))); Action <Position> addPositionMaybe = position => { if (!position.isClosed()) { return; } var pnl = position.pnl(true, simulator.runInNativeCurrency()); var color = pnl > 0 ? Color.Green : (pnl < 0 ? Color.Red : Color.Black); var line = AddCurve("", new PointPairList { { dateParent.index(position.entry().time), position.entry().price }, { dateParent.index(position.exitTrade().time), position.exitTrade().price } }, color); line.Symbol.IsVisible = false; line.Line.Style = DashStyle.Dot; line.Line.Width = 2; line.Label.IsVisible = false; line.IsOverrideOrdinal = true; }; Objects.each(positions, addPositionMaybe); simulator.addNewTradeListener((position, trade) => { if (!position.symbol.Equals(symbol)) { return; } addTrade(trade, bars.count()); addPositionMaybe(position); }); }