Back to Devexpress

How to: Plot an XY Series with a Histogram in a Chart

wpf-403342-controls-and-libraries-charts-suite-chart-control-examples-providing-data-how-to-plot-an-xy-series-with-a-histogram-in-a-chart.md

latest9.2 KB
Original Source

How to: Plot an XY Series with a Histogram in a Chart

  • Dec 20, 2022
  • 4 minutes to read

The following example shows how to plot an XY series with a histogram in the same chart:

In this example, a Line series displays a normal distribution curve on the secondary axis and is aligned with a histogram on the primary axis.

View Example: How to: Plot an XY Series with a Histogram in a Chart

csharp
using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace SideBySideBar2DChart {
    public partial class Window1 : Window {
        public Window1() {
            InitializeComponent();
        }
    }

    public class ViewModel {
        const int HistogramPointsCount = 1000;
        const int DistributionPointsCount = 100;
        const double Mean = 0.5;
        const double StdDev = 0.15;
        const double Max = 10;

        Random random = new Random();

        public ObservableCollection<DataPoint> NormalDistribution { get; private set; }
        public ObservableCollection<DataPoint> Histogram { get; private set; }
        public double MinValue { get { return 0; } }
        public double MaxValue { get { return Max; } }
        public double BinCount { get { return 20; } }

        public ViewModel() {
            CreateDataSource();
        }
        void CreateDataSource() {
            NormalDistribution = new ObservableCollection<DataPoint>();
            for(int i = 0; i < DistributionPointsCount; i++) {
                double x = i * Max / DistributionPointsCount;
                NormalDistribution.Add(new DataPoint(x, GetNormalDistribution(x, Mean * Max, StdDev * Max)));
            }
            Histogram = new ObservableCollection<DataPoint>();
            for(int x = 0; x < HistogramPointsCount; x++)
                Histogram.Add(new DataPoint(GenerateHistogramPoint(Mean * Max, StdDev * Max)));
        }
        double GetNormalDistribution(double x, double mean, double stdDev) {
            double tmp = 1 / (Math.Sqrt(2 * Math.PI) * stdDev);
            return Math.Exp(-Math.Pow(x - mean, 2) / (2 * Math.Pow(stdDev, 2))) * tmp;
        }
        double GenerateHistogramPoint(double mean, double stdDev) {
            return Math.Sqrt(-2 * Math.Log(random.NextDouble())) * Math.Cos(2 * Math.PI * random.NextDouble()) * stdDev + mean;
        }
    }
}
vb
Imports System
Imports System.Collections.ObjectModel
Imports System.Windows

Namespace SideBySideBar2DChart

    Public Partial Class Window1
        Inherits Window

        Public Sub New()
            Me.InitializeComponent()
        End Sub
    End Class

    Public Class ViewModel

        Private _NormalDistribution As ObservableCollection(Of SideBySideBar2DChart.DataPoint), _Histogram As ObservableCollection(Of SideBySideBar2DChart.DataPoint)

        Const HistogramPointsCount As Integer = 1000

        Const DistributionPointsCount As Integer = 100

        Const Mean As Double = 0.5

        Const StdDev As Double = 0.15

        Const Max As Double = 10

        Private random As Random = New Random()

        Public Property NormalDistribution As ObservableCollection(Of DataPoint)
            Get
                Return _NormalDistribution
            End Get

            Private Set(ByVal value As ObservableCollection(Of DataPoint))
                _NormalDistribution = value
            End Set
        End Property

        Public Property Histogram As ObservableCollection(Of DataPoint)
            Get
                Return _Histogram
            End Get

            Private Set(ByVal value As ObservableCollection(Of DataPoint))
                _Histogram = value
            End Set
        End Property

        Public ReadOnly Property MinValue As Double
            Get
                Return 0
            End Get
        End Property

        Public ReadOnly Property MaxValue As Double
            Get
                Return Max
            End Get
        End Property

        Public ReadOnly Property BinCount As Double
            Get
                Return 20
            End Get
        End Property

        Public Sub New()
            CreateDataSource()
        End Sub

        Private Sub CreateDataSource()
            NormalDistribution = New ObservableCollection(Of DataPoint)()
            For i As Integer = 0 To DistributionPointsCount - 1
                Dim x As Double = i * Max / DistributionPointsCount
                NormalDistribution.Add(New DataPoint(x, GetNormalDistribution(x, Mean * Max, StdDev * Max)))
            Next

            Histogram = New ObservableCollection(Of DataPoint)()
            For x As Integer = 0 To HistogramPointsCount - 1
                Histogram.Add(New DataPoint(GenerateHistogramPoint(Mean * Max, StdDev * Max)))
            Next
        End Sub

        Private Function GetNormalDistribution(ByVal x As Double, ByVal mean As Double, ByVal stdDev As Double) As Double
            Dim tmp As Double = 1 / (Math.Sqrt(2 * Math.PI) * stdDev)
            Return Math.Exp(-Math.Pow(x - mean, 2) / (2 * Math.Pow(stdDev, 2))) * tmp
        End Function

        Private Function GenerateHistogramPoint(ByVal mean As Double, ByVal stdDev As Double) As Double
            Return Math.Sqrt(-2 * Math.Log(random.NextDouble())) * Math.Cos(2 * Math.PI * random.NextDouble()) * stdDev + mean
        End Function
    End Class
End Namespace
xaml
<Window
    x:Class="SideBySideBar2DChart.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/charts"
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
    xmlns:local="clr-namespace:SideBySideBar2DChart"
    Width="820.806"
    Height="354.032"
    DataContext="{dxmvvm:ViewModelSource Type=local:ViewModel}"
    Title="WPF Chart">
    <Grid>
        <dxc:ChartControl Name="chartControl1">
            <dxc:ChartControl.Diagram>
                <dxc:XYDiagram2D x:Name="diagram">
                    <dxc:XYDiagram2D.AxisX>
                        <dxc:AxisX2D Name="primaryAxisX" Visible="True">
                            <dxc:AxisX2D.WholeRange>
                                <dxc:Range
                                    MaxValue="{Binding MaxValue}"
                                    MinValue="{Binding MinValue}"
                                    SideMarginsValue="0" />
                            </dxc:AxisX2D.WholeRange>
                            <dxc:AxisX2D.NumericScaleOptions>
                                <dxc:CountIntervalNumericScaleOptions
                                    Count="{Binding BinCount}"
                                    GridLayoutMode="GridShiftedLabelCentered"
                                    Pattern="{}{OB}{A1:F1}, {A2:F1}{CB}" />
                            </dxc:AxisX2D.NumericScaleOptions>
                        </dxc:AxisX2D>
                    </dxc:XYDiagram2D.AxisX>

                    <dxc:XYDiagram2D.SecondaryAxesX>
                        <dxc:SecondaryAxisX2D Name="secondaryAxisX" Visible="False">
                            <dxc:SecondaryAxisX2D.NumericScaleOptions>
                                <dxc:ContinuousNumericScaleOptions />
                            </dxc:SecondaryAxisX2D.NumericScaleOptions>
                            <dxc:SecondaryAxisX2D.WholeRange>
                                <dxc:Range SideMarginsValue="0" />
                            </dxc:SecondaryAxisX2D.WholeRange>
                        </dxc:SecondaryAxisX2D>
                    </dxc:XYDiagram2D.SecondaryAxesX>

                    <dxc:XYDiagram2D.SecondaryAxesY>
                        <dxc:SecondaryAxisY2D Name="secondaryAxisY" />
                    </dxc:XYDiagram2D.SecondaryAxesY>

                    <dxc:XYDiagram2D.Series>
                        <dxc:BarStackedSeries2D
                            AggregateFunction="Histogram"
                            ArgumentDataMember = "XValue"
                            ArgumentScaleType="Numerical"
                            BarWidth="1"
                            DataSource="{Binding Histogram}"
                            DisplayName="Histogram" />

                        <dxc:SplineSeries2D
                            AggregateFunction="None"
                            ArgumentDataMember = "XValue"
                            ArgumentScaleType="Numerical"
                            AxisX="{Binding ElementName=secondaryAxisX}"
                            AxisY="{Binding ElementName=secondaryAxisY}"
                            DataSource="{Binding NormalDistribution}"
                            DisplayName="Normal Distribution"
                            ValueDataMember = "YValue" />

                    </dxc:XYDiagram2D.Series>
                </dxc:XYDiagram2D>
            </dxc:ChartControl.Diagram>
        </dxc:ChartControl>
    </Grid>
</Window>

See Also

Histogram