[FlexChart]Display error bar for each point

Posted by: a.sharov on 19 November 2021, 12:28 pm EST

    • Post Options:
    • Link

    Posted 19 November 2021, 12:28 pm EST

    Hi.

    I have data – value, it’s confidence interval and datetime. I want to display

    error bar for each value.

    I have following coniguration code:

    
                flexChart3.Series.Clear();
    
                var valueCoord = new Series
                {
                        Name = "value",
                        Binding = "Value",
                        BindingX = "Date",
                        ChartType = ChartType.LineSymbols,
                        Style =
                        {
                                FillColor = Settings.Default.MainChartColor,
                                StrokeColor = Settings.Default.MainChartColor
                        }
                };
                flexChart3.Series.Add(valueCoord);
    
                var bar = new ErrorBar
                {
                        BindingX = "Date",
                        Binding = "Sigma",
                        
                        Name = "Sigma1",
                        ErrorAmount = ErrorAmount.StandardError
                };
    
                flexChart3.Series.Add(bar);
    
    
                flexChart3.ToolTip.Content = $"{ComponentName} : {{Value}}\rDate: {{Date}}";
    
    

    and datasource class

    
     public class Class
        {
            #region Properties
    
            public double Value { get; set; }
            public DateTime Date { get; set; }
            public double Sigma { get; set; }
            #endregion
        }
    
    

    (datasoruce is collection of Class entities)

    So, for each value I have some sigma (or conf. interval) and I want to display it as error bar. How can I achieve this?

    Thanks in advance

  • Posted 22 November 2021, 4:50 am EST

    Hi Anton,

    Thank you for sharing the code snippet.

    By default FlexChart’s ErrorBar supports displaying same error value for all the data points. However, you can manually render bars according to your Sigma value by using ErrorBar’s SymbolRendered event as follows:

    
    private void OnSymbolRendered(object sender, RenderSymbolEventArgs e)
    {
                var dataItem = e.Item as DataItem;
                double errorValue = dataItem.Sigma;
                var engine = e.Engine;
                double x = e.Point.X;
                double y = e.Point.Y;
    
                engine.SetStroke(Brushes.Black);
                engine.SetStrokeThickness(1);
    
                var upperPoint = ActualChart.DataToPoint(new Point(0, dataItem.Y + errorValue)); // gets the point upto where upper bar needs to be drawn
                var lowerPoint = ActualChart.DataToPoint(new Point(0, dataItem.Y - errorValue));// gets the point upto where upper lower needs to be drawn
    
                // Drawing bars
                switch (Direction)
                {
                    case ErrorBarDirection.Both:
                        // Uper bar line                 
                        e.Engine.DrawLine(x, y, x, upperPoint.Y);
    
                        // lower bar line
                        e.Engine.DrawLine(x, y, x, lowerPoint.Y);
                        break;
    
                    case ErrorBarDirection.Minus:
                        // lower bar line                   
                        e.Engine.DrawLine(x, y, x, lowerPoint.Y);
                        break;
    
                    case ErrorBarDirection.Plus:
                        // Uper bar line
                        e.Engine.DrawLine(x, y, x, upperPoint.Y);
                        break;
                }
    
                // Drawing cap
                switch (EndStyle)
                {
                    case ErrorBarEndStyle.Cap:
    
                        switch (Direction)
                        {
                            case ErrorBarDirection.Both:
                                DrawCap(engine, x, upperPoint.Y, 10);
                                DrawCap(engine, x, lowerPoint.Y, 10);
                                break;
    
                            case ErrorBarDirection.Minus:
                                DrawCap(engine, x, lowerPoint.Y, 10);
                                break;
    
                            case ErrorBarDirection.Plus:
                                DrawCap(engine, x, upperPoint.Y, 10);
                                break;
                        }
    
                        break;
                }
    }
    
    

    Please refer to the attached sample for full implementation. (see FlexChartErrorBar.zip)

    JFYI, the attached sample shows implementation of fixed value error bars. So, in case you want any other error value bars i.e. StandardDeviation/StandardError etc. then you can modify the code accordingly.

    Best Regards,

    Kartik

    FlexChartErrorBar.zip

  • Posted 24 November 2021, 5:10 pm EST

    Hi. Thank you for reply.

    It didn’t work for me. Also I’m using winforms.

    Here is my code snippet:

    
          private void SetupChart()
            {
                flexChart3.Series.Clear();
    
                var valueCoord = new Series
                {
                        Name = "value",
                        Binding = "Value",
                        BindingX = "Date",
                        ChartType = ChartType.LineSymbols,
                        Style =
                        {
                                FillColor = Settings.Default.MainChartColor,
                                StrokeColor = Settings.Default.MainChartColor
                        }
                };
                flexChart3.Series.Add(valueCoord);
    
                var bar = new ErrorBar
                {
                        BindingX = "Date",
                        Binding = "Sigma",
                        Name = "errorbar",
                       //ErrorAmount = ErrorAmount.StandardError
                };
                bar.SymbolRendered += Bar_SymbolRendered;
                flexChart3.Series.Add(bar);
    
    
                flexChart3.ToolTip.Content = $"{ComponentName} : {{Value}}\rDate: {{Date}}";
    
    
                //Add zones to legend
                for (var i = 0; i < 6; i++)
                {
                    var series = new Series {ChartType = ChartType.Area};
                    series.Style.Fill = new SolidBrush(_zonesColors[i]);
                    series.Style.Stroke = new SolidBrush(Color.Transparent);
                    flexChart3.Series.Add(series);
                }
             //NOTE took from flexchart samples to draw different color regions.
                flexChart3.Rendering += FlexChart1Rendering;
            }
    
            private void Bar_SymbolRendered(object sender, RenderSymbolEventArgs e)
            {
                var dataItem = e.Item as Pos;
                double errorValue = dataItem.Sigma;
                var engine = e.Engine;
                double x = e.Point.X;
                double y = e.Point.Y;
                
                engine.SetStroke(Brushes.Black);
                engine.SetStrokeThickness(1);
    
                var upperPoint = flexChart3.DataToPoint(new Point(0, (int)(dataItem.Value + errorValue))); // gets the point upto where upper bar needs to be drawn
                var lowerPoint = flexChart3.DataToPoint(new Point(0, (int)(dataItem.Value - errorValue)));// gets the point upto where upper lower needs to be drawn
    
                // Drawing bars
                var errorBar = e.Series as ErrorBar;
                Debug.Assert(errorBar != null, nameof(errorBar) + " != null");
    
                switch (errorBar.Direction)
                {
                    case ErrorBarDirection.Both:
                        // Uper bar line                 
                        e.Engine.DrawLine(x, y, x, upperPoint.Y);
    
                        // lower bar line
                        e.Engine.DrawLine(x, y, x, lowerPoint.Y);
                        break;
    
                    case ErrorBarDirection.Minus:
                        // lower bar line                   
                        e.Engine.DrawLine(x, y, x, lowerPoint.Y);
                        break;
    
                    case ErrorBarDirection.Plus:
                        // Uper bar line
                        e.Engine.DrawLine(x, y, x, upperPoint.Y);
                        break;
                }
    
                // Drawing cap
                switch (errorBar.EndStyle)
                {
                    case ErrorBarEndStyle.Cap:
    
                        switch (errorBar.Direction)
                        {
                            case ErrorBarDirection.Both:
                                DrawCap(engine, x, upperPoint.Y, 10);
                                DrawCap(engine, x, lowerPoint.Y, 10);
                                break;
    
                            case ErrorBarDirection.Minus:
                                DrawCap(engine, x, lowerPoint.Y, 10);
                                break;
    
                            case ErrorBarDirection.Plus:
                                DrawCap(engine, x, upperPoint.Y, 10);
                                break;
                        }
    
                        break;
                }
            }
    
    
            private void DrawCap(IRenderEngine engine, double x, double y, double width)
            {
                var halfWidth = width / 2;
                engine.DrawLine(x - halfWidth, y, x + halfWidth, y);
            }
    
    
    
  • Posted 25 November 2021, 5:00 pm EST

    Hi again.

    I managed to solve with following code:

    
       var valueCoord = new Series
                {
                        Name = "value",
                        Binding = "Value",
                        BindingX = "Date",
                        ChartType = ChartType.LineSymbols,
                        Style =
                        {
                                FillColor = Settings.Default.MainChartColor,
                                StrokeColor = Settings.Default.MainChartColor
                        }
                };
                flexChart3.Series.Add(valueCoord);
                valueCoord.SymbolRendered += BarSymbolRendered;
          //NOTE no error bar any more
    ...
    
       private void BarSymbolRendered(object sender, RenderSymbolEventArgs e)
            {
                var dataItem = e.Item as MonPosition;
                var errorValue = (float)dataItem.Sigma;
    
    
                var engine = e.Engine;
                double x = e.Point.X;
                double y = e.Point.Y;
    
                
    
                engine.SetStroke(Brushes.Black);
                engine.SetStrokeThickness(1);
    
                var upperPoint =
                        flexChart3.DataToPoint(new PointF(0, (float)(dataItem.Value + errorValue)));
                var lowerPoint =
                        flexChart3.DataToPoint(new PointF(0, (float)(dataItem.Value - errorValue)));
    
                var temp = Math.Max(Math.Abs(dataItem.Value + errorValue), Math.Abs(dataItem.Value - errorValue));
                _axisYSigmaMax = Math.Max(temp, _axisYSigmaMax);
                
                e.Engine.DrawLine(x, y, x, upperPoint.Y + errorValue);
                e.Engine.DrawLine(x, y, x, lowerPoint.Y - errorValue);
    
                DrawCap(engine, x, upperPoint.Y, 10);
                DrawCap(engine, x, lowerPoint.Y, 10);
    
            }
    
    

    This seems to be working, but still I hope on your reponse about proper approach, because in code above I’ve excluded ErrorBar series.

  • Posted 25 November 2021, 5:04 pm EST - Updated 3 October 2022, 10:53 pm EST

    Also in image above see some strange artifacts when bar are cut or point is left from chart.

    What can the cause of it?

  • Posted 26 November 2021, 8:38 am EST

    Hi Anton,

    Do you want to show the complete error bar in view?

    Additionally, could you please share the sample you are using?

    Regards,

    Kartik

  • Posted 26 November 2021, 1:55 pm EST

    Hi.

    Do you want to show the complete error bar in view?

    What is complete error bar in view?

    I don’t know, I’m ok with current solution (code above + picture). But maybe instead of “hacking” there is some convetional solutions with ErrorBar series class. I supposed that I can achieve the same without additional events and drawing code, rather some configuration.

    https://drive.google.com/file/d/1ib1wes-quVN43TvJw10XNNJNEVYEqFAx/view?usp=sharing

    See link for code above. It is basically merge of 3 samples from your FlexChartSamples – aggregation, range selector, and zone coloring. I even left comments untouched for a while.

    Look in code for “//temp solution” comment. In a screen above I solve the problem with left point outside by extending (deceasing) min date of last point I show. (I show fixed number of points, def ==5, after new pnt is added, select 5 last pnts, choose first, get it’s date and shift by 5 mins). Points are shown correct, within a bound, but still empty space is present (you can see it my pic. above, on the left empty space is present).

    Also I have problem with axisY (search for "//need help here " comment in code). I want to split my chart into 3 regions colored green, yellow and red. Code is taken from your samples and slightly modified. So I have problems with upper (highest) and lower (lowest) sigma bars (see pic.).

    Any suggestions for improvements appreciated.

  • Posted 27 November 2021, 2:58 am EST

    Hi Anton,

    > I supposed that I can achieve the same without additional events and drawing code, rather some configuration.

    JFYI, ErrorBar series only supports same error value for all error bars. Therefore, in order to support different error value with each error bar the only possible way is to manually render the error bars.

    > Points are shown correct, within a bound, but still empty space is present

    We are sorry but this behavior is not reproducible at our end. Could you please share a working sample replicating this behavior so that we can assist you accordingly?

    > So I have problems with upper (highest) and lower (lowest) sigma bars

    I can observe the sigma bar is getting cropped out of chart. It might be possible that the upper value of the bar is lying outside the char bounds which is expected. Could you please elaborate as I am not able to properly understand the issue here?

    Kind Regards,

    Kartik

  • Posted 29 November 2021, 1:26 pm EST

    Hi.

    JFYI, ErrorBar series only supports same error value for all error bars. Therefore, in order to support different error value with each error bar the only possible way is to manually render the error bars.

    Ok, clear. Btw, what is enum ErrorAmount is used for?

    We are sorry but this behavior is not reproducible at our end. Could you please share a working sample replicating this behavior so that we can assist you accordingly?

    Exe file would be enough or code is needed ?

    I can observe the sigma bar is getting cropped out of chart. It might be possible that the upper value of the bar is lying outside the char bounds which is expected. Could you please elaborate as I am not able to properly understand the issue here?

    Yes, it cropped. I linked main source file above, all manipulations with chart are within this source file. If it is still not enough then I will try to provide full sources. But this is the only one which works with controls.

  • Posted 30 November 2021, 1:23 am EST

    Hi Anton,

    > Btw, what is enum ErrorAmount is used for

    ErrorAmount enum is used to specify the error amount type for the series. For example, if the ErrorBar’s ErrorValue is set to 30 and ErrorAmount is set to Percentage then each bar error value will be 30% of the data item bound value present at the error bar position. But, since you are manually rendering the error bars because of different error values then ErrorAmount will be of no use.

    https://www.grapecity.com/componentone/docs/wpf/online-flexchart/C1.WPF.FlexChart.4.5.2~C1.Chart.ErrorAmount.html

    > Exe file would be enough or code is needed ?

    I would request you to share the working application along with the code.

    > Yes, it cropped. I linked main source file above, all manipulations with chart are within this source file

    In order to prevent cropping, you can set the AxisY’s Max property based on the error value while drawing error bars inside Series’s SymbolRendering event. Just in case if that didn’t work then please share the sample application so that we can modify it accordingly.

    Regards,

    Kartik

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels