Bubble Series Performance

When using a bubble series chart that has the ListenPropertyChanged set to true for listening to live data, we notice a considerable performance drop when running over one thousand data points on the graph.

We require the ability to have the size of the bubbles scaled (averaged), as well as colouring them based on the x,y coordinate of the data point.
I've looked into the scatter chart to plot the data as the documentation states it is more efficient when it comes to plotting larger data sets, but unfortunately it looks like it does not allow for sizing/colouring of each point. 

Would there be a way around this with the Scatter chart, or if we could get some clarification as to how many points can be displayed on a Bubble series that is displaying live data?

Regards,
Andrew.

9 Replies

DD Devakumar Dhanapoosanam Syncfusion Team April 5, 2020 07:04 PM UTC

Hi Andrew, 
 
Greetings from Syncfusion. 
 
We have analyzed your query using BubbleSeries performance drop with huge data point, and we would like to suggest using the FastScatterSeries instead of BubbleSeries when having huge data points to improve performance.  
 
Query: unfortunately, it looks like ScatterSeries does not allow for sizing/coloring of each point.  
 
Yes, the FastScatterSeries do not support the individual size and color feature as in the BubbleSeries. But we can increase the size of the FastScatterSeries using the ScatterWidth and ScatterHeight to make the bubble size average commonly for each point.  
 
 
Can you please provide more details regarding your requirement while adding 1000 datapoints which will be helpful for us to analyze and provide a possible solution? 
·       Please let us know whether your requirement is to set color for the individual scatter datapoint or for some specific range you were trying to set a color?   
·       Can you please share any pictorial representation of your requirement using the ScatterSeries with the color behavior? 
·       Please let us know whether you were adding any other additional series along with the ScatterSeries or not? 
  
Regards, 
Devakumar D 



DL dorsaVi Ltd April 5, 2020 11:43 PM UTC

Thanks for the reply Devakumar.

We want to plot x,y data that gets streamed from a bluetooth sensor. My hope was that the Bubble Series would be a suitable replacement for a heatmap since this type of chart is unavailable for Xamarin.Forms.

When the sensors tilt angle stays in a particular x,y position long enough, that bubble increases in size, while the others shrink (essentially showing an average). It's position will also determine it's color.

We would like to plot a lot more than 1000 points as well. 1000 was just where performance began to drop for us.
I'm unsure if the performance hit is when the chart calculates the sizing for all the points, or the rendering?


An example of our most preferred end result would plot the following color ranges;

Y Axis: 
  • -45 to -10 (Red)
  • -9 to -5 (Amber)
  • -4 to 19 (Green)
  • 20 to 39 (Amber)
  • 40 to 130 (Red)
X Axis
  • -45 to -10 (Red)
  • -9 to -5 (Amber)
  • -4 to 4 (Green)
  • 5 to 9 (Amber)
  • 10 to 45 (Red)
The above ranges would display a graph similar to the image attached (the egg shape is important, but as a first step I am just attempting the basics).
No other series would need to be displayed on this graph, just the x,y averages.

Alternatively, if we can get the colors on a FastScatterSeries, I could play around with opacity per point as a replacement for size, if sizing is not possible?

Thank you for your help on this.
Andrew.


Attachment: Image_9a236f08.zip


DL dorsaVi Ltd April 6, 2020 01:38 AM UTC

I have made some progress with this today with the Bubble Series. 
I've converted the data being observed from a List<T> to an ObservableCollection<T>, and this appears to has drastically improved performance.
Along with only generating the required points of data instead of starting with the full set.

This has taken me from the app running at approximately 0.25fps to 30fps.

I would like to still attempt the FastScatterSeries if that is an option with coloring.

Regards,
Andrew


DD Devakumar Dhanapoosanam Syncfusion Team April 6, 2020 12:56 PM UTC

Hi Andrew, 
 
Thanks for your update and sharing the requested details. 
 
Currently we are working on your requirement and will update further details on April 7, 2020.  
 
Regards, 
Devakumar D 



DD Devakumar Dhanapoosanam Syncfusion Team April 7, 2020 07:44 PM UTC

 
Thanks for your patience. 
 
Due to technical blocks we were unable to set color for each scatter points. 
 
We would like to suggest the available coloring customization using the FastScatterSeries by using the CustomGradientColors and by providing the GradientStops Offset values for the range as per your requirement as in the below code snippet, 
 
XAML: 
<chart:SfChart x:Name="chart" HorizontalOptions="FillAndExpand" 
                          VerticalOptions="FillAndExpand"> 
     …. 
     <chart:FastScatterSeries ItemsSource="{Binding Data}" 
                                 XBindingPath="XValue" 
                                 YBindingPath="YValue" 
                                 ScatterWidth="10" ScatterHeight="10" 
                                 EnableAntiAliasing="False"> 
     </chart:FastScatterSeries> 
     <chart:SfChart.ColorModel> 
                <chart:ChartColorModel Palette="Custom" 
                                       CustomGradientColors="{Binding GradientColors}"> 
                </chart:ChartColorModel> 
     </chart:SfChart.ColorModel> 
      
</chart:SfChart>  
 
C#: [ViewModel.cs] 
GradientColors = new ChartGradientColorCollection() 
         { 
               new ChartGradientColor() 
               { 
                   StartPoint = new Point(0.5, 1) , EndPoint = new Point(0.5,0), 
                   GradientStops = new ChartGradientStopCollection() 
                    { 
                        new ChartGradientStop(){Offset = 0.30f, Color = Color.Green}, 
                        new ChartGradientStop(){Offset = 0.30f, Color = Color.Yellow}, 
                        new ChartGradientStop(){Offset = 0.50f, Color = Color.Yellow}, 
                        new ChartGradientStop(){Offset = 0.50f, Color = Color.Orange}, 
                        new ChartGradientStop(){Offset = 0.65f, Color = Color.Orange}, 
                        new ChartGradientStop(){Offset = 0.65f, Color = Color.Red}, 
                   } 
               } 
         }; 
 
Screenshot: 
 
 
 
Based on the provided image we would like to suggest using multiple FastScatterSeries only incase if it is possible to collect/get the separate set of datapoints for each part in egg and you can set the color as per your requirement for each series and also able to increase the scatter size for any particular series.  
 
In case, if you are working with live data, please refer the below steps to optimize the chart performance:  
 
·       We can able to hold the chart from updating of each data added to the collection, using SuspendSeriesNotification and ResumeSeriesNotification methods in chart control, the chart will not respond to any change in the items source collection after the SuspendSeriesNotification method is invoked. It will be updated with latest data after the ResumeSeriesNotification method is invoked. 
     Try to remove the data which is not visible in view. 
     Try adding bulk data instead of adding single data points with some delay.  
·       Try to update the collection in background thread instead of updating in UI main thread. 
·       Use DateTimeAxis and NumericalAxis instead of CategoryAxis.    
·       Set the StrokeWidth of FastLineSeries to 1 by default its value is 2.   
·       Set the EnableAntiAliasing property as false for FastLineSeries, FastScatterSeries. 
 
C#: 
public class ViewModel 
{ 
        …. 
        public Action BeginDataUpdate; 
        public Action EndDataUpdate; 
} 
 
public partial class MainPage : ContentPage 
{ 
        ViewModel viewModel; 
        …. 
        public MainPage() 
        { 
            InitializeComponent(); 
 
            viewModel = new ViewModel(); 
            this.BindingContext = viewModel; 
 
            viewModel.BeginDataUpdate = () => chart.SuspendSeriesNotification(); 
            viewModel.EndDataUpdate = () => chart.ResumeSeriesNotification(); 
        } 
        …. 
        public async void LoadData() 
        { 
                await Task.Delay(500); 
                 //dynamic change data using suspend and resume  
                 Device.BeginInvokeOnMainThread(() => 
                 { 
                        //chart.SuspendSeriesNotification() is called when using below code. 
                        viewModel.BeginDataUpdate(); 
 
                         for (int i = 0; k < 128; k++) 
                         { 
                               //Add Data 
                         } 
                         //chart.ResumeSeriesNotification() is called when using below code. 
                         viewModel.EndDataUpdate();  
                  });  
               …. 
         } 
} 
 
 
Please let us know whether the above suggestion helps for your requirement or not. 
 
Regards, 
Devakumar D 



DL dorsaVi Ltd April 7, 2020 11:53 PM UTC

Thank you for the in depth feedback!

I may be able to work around this with the gradient as suggested. It gives me a good starting point.
I am hopeful the the optimisation steps you have provided will work for our implementation, and I will work through those in the coming days.

Thanks again,
Andrew.


DL dorsaVi Ltd April 8, 2020 05:10 AM UTC

I seem to have the Bubble series working as I need it to with some of the optimisation tips you have provided.
I played around with the FastScatterSeries, and while I managed to get something working, the lack of opacity or size changes per point will not work for us.

I had one final follow up question about the bubble series.

I am using a custom brushes to assign each dot a color.
This works if the graph has all its points loaded prior to setting up the color brush, however when I attempt to set the color brush on a graph with no data loaded beforehand, and then proceed to plot my data points, all dots are drawn as a same color. 

I am not sure if this is a bug or a limitation.

Due to the number of points I am drawing, I would like to be able to not have to plot all the data prior to assigning the custom brush, as doing so will cause a delay in the program. 

I have added the xaml code for the bubble series for clarification;

<chart:SfChart HorizontalOptions="FillAndExpand"
                                   VerticalOptions="FillAndExpand"
                                   BackgroundColor="{DynamicResource Background}"
                                   AreaBackgroundColor="{DynamicResource Background}"
                                   Margin="0,0,40,0">
                        <chart:BubbleSeries ItemsSource="{Binding GraphData}"
                                            XBindingPath="XElevation"
                                            YBindingPath="YElevation"
                                            Size="Count"
                                            MinimumRadius="0"
                                            MaximumRadius="5"
                                            StrokeWidth="1"
                                            ListenPropertyChange="True">
                            <chart:BubbleSeries.ColorModel>
                                <chart:ChartColorModel Palette="Custom"
                                                       CustomBrushes="{Binding GraphColors}"/>
                            </chart:BubbleSeries.ColorModel>
                        </chart:BubbleSeries>
                        <chart:SfChart.PrimaryAxis>
                            <chart:NumericalAxis Minimum="-45"
                                                 Maximum="45"
                                                 Interval="10"
                                                 ShowMajorGridLines="False">
                                <chart:NumericalAxis.AxisLineStyle>
                                    <chart:ChartLineStyle StrokeWidth="2"
                                                          StrokeColor="{DynamicResource OnBackground}">
                                    </chart:ChartLineStyle>
                                </chart:NumericalAxis.AxisLineStyle>
                                <chart:NumericalAxis.LabelStyle>
                                    <chart:ChartAxisLabelStyle TextColor="{DynamicResource OnBackground}"
                                                               FontSize="10"/>
                                </chart:NumericalAxis.LabelStyle>
                                <chart:NumericalAxis.Title>
                                    <chart:ChartAxisTitle Text="Horizontal Motion"
                                                          TextColor="{DynamicResource OnBackground}"/>
                                </chart:NumericalAxis.Title>
                            </chart:NumericalAxis>
                        </chart:SfChart.PrimaryAxis>
                        <chart:SfChart.SecondaryAxis>
                            <chart:NumericalAxis Minimum="-40"
                                                 Maximum="120"
                                                 Interval="20"
                                                 ShowMajorGridLines="False">
                                <chart:NumericalAxis.AxisLineStyle>
                                    <chart:ChartLineStyle StrokeWidth ="2"
                                                          StrokeColor="{DynamicResource OnBackground}">
                                    </chart:ChartLineStyle>
                                </chart:NumericalAxis.AxisLineStyle>
                                <chart:NumericalAxis.LabelStyle>
                                    <chart:ChartAxisLabelStyle TextColor="{DynamicResource OnBackground}"
                                                               FontSize="10"/>
                                </chart:NumericalAxis.LabelStyle>
                                <chart:NumericalAxis.Title>
                                    <chart:ChartAxisTitle Text="Vertical Motion"
                                                          TextColor="{DynamicResource OnBackground}"/>
                                </chart:NumericalAxis.Title>
                            </chart:NumericalAxis>
                        </chart:SfChart.SecondaryAxis>
                    </chart:SfChart>




DL dorsaVi Ltd April 8, 2020 06:03 AM UTC

I have managed to solve my last query.

I did not realise that the location of the color value in the ObservableCollection was matched to the location of the Data points ObservableCollection.
Updating the Colors ObservableCollection dynamically when a new Data point was added fixed my issue.

Thank you for all the help you and your team has provided me this week!


DD Devakumar Dhanapoosanam Syncfusion Team April 8, 2020 01:24 PM UTC

Hi Andrew, 
 
Thanks for your update. 
 
We are glad to hear that you resolved the reported issue and able to achieve your requirement. 
 
Please let us know if you need any further assistance. 
 
Regards, 
Devakumar D 


Loader.
Up arrow icon