I want to create a chart like the attached image file.
I want to mark points with different colors depending on the number of data corresponding to the x and y axes.
As a result of searching, there is a HeatmapColorPalette. Is it good to use this?
If there is a more suitable chart, please introduce it.
thank you
- Seung Woo Jin asked 1 year ago
- last active 1 year ago
Hello SciChart team,
we have a problem with column series in 2D. At certain values in the X-axis, the bars in the chart overlap.
We found that the bar width is calculated incorrectly only from a certain distance between the values on the X-axis. There seems to be a bug in the calculation of the minimum bar width.
I’ve already seen issues related to a similar problem with the non-equidistant axis values and have already tried the “UseUniformWidth” property. Unfortunately without success. In principle, however, it seems to work with the non-equidistant axis values (ColumnChart1.png). As soon as the value is changed from 16 to 18, the bars overlap (ColumnChart2.png). In the application we need the width at 100%.
I’ve also attached an example project that can be used to reproduce the error.
Best regards
Silvester
- Silvester Schneidt asked 2 years ago
- last active 2 years ago
Hello,
I’m trying to get a scatter series chart to work but it doesn’t render. For Bar, Impulse, and Line I can use the same code only switching the series type, but when I attempt to do the same with Scatter series (both XyScatter and ExtremeScatter) the points don’t render.
Here is my scatter series code:
// ...
for (int i = 0; i < dimensions; i++)
{
var scatterSeries = new ExtremeScatterRenderableSeries()
{
PointMarker = new EllipsePointMarker() { Width = 7, Height = 7}
};
scatterSeries.PaletteProvider = new ExtremeScatterPaletteProvider(colors);
Binding DataSeriesBinding = new Binding("Data");
DataSeriesBinding.Source = (_cvm as ChartViewModelXY).ndData.ElementAt(i);
scatterSeries.SetBinding(BaseRenderableSeries.DataSeriesProperty, DataSeriesBinding);
Chart.RenderableSeries.Add(scatterSeries);
permanentLineSeries++;
}
// ...
public class ExtremeScatterPaletteProvider : IExtremePointMarkerPaletteProvider
{
private readonly List<Color> _dataPointColors;
private readonly Values<Color> _colors = new Values<Color>();
public ExtremeScatterPaletteProvider(List<Color> dataPointColors)
{
_dataPointColors = dataPointColors;
}
// Fill Colors for each data-point index
public Values<Color> Colors { get { return _colors; } }
public void OnBeginSeriesDraw(IRenderableSeries rSeries)
{
var indexes = rSeries.CurrentRenderPassData.PointSeries.Indexes;
var count = indexes.Count;
_colors.Count = count;
// copy required colors from list using data point indices
for (int i = 0; i < count; i++)
{
var dataPointIndex = indexes[i];
_colors[i] = _dataPointColors[dataPointIndex];
}
}
}
The same code works with 3 other XY charts, so I’m fairly certain the issue is with how I am creating the ExtremeScatter. Any help or insight would be greatly appreciated!
Edit: For anyone curious / googling a fully instantiated XyScatterRenderableSeries in code looks like this:
// Render a scatter series
var scatterSeries = new XyScatterRenderableSeries()
{
PointMarker = new EllipsePointMarker() { Width = 7, Height = 7, Stroke = colors[i], Fill = colors[i]}
};
That will render the series with the same color for both the border and interior.
- Matt Carroll asked 5 years ago
- last active 5 years ago
Hello,
I have been working with an application that plots real-time serial data using a FIFO buffer. I have started programming around the ECG-Monitor example as this is exactly what I am creating.
I have a device that broadcasts real-time ECG data via Bluetooth (HC-05), to be exact. I have paired the device and opened a SerialPort in my program to receive the data. My sampling rate is 256 Hz.
When I used a text file to simulate ECG data, it works perfectly well. However, when I use real-time data, there is a delay in charting that increases as the time increases. An easier way to understand this is, the chart continues plotting for a significant period of time even after I have switched off my hardware device.
I have then come to the conclusion that my data is being received at the rate that I want it to, but the plotting gets delayed at an increasing rate as the time increases.
I am currently using the Direct-X rendering type as this gives me a very smooth plot. I receive the data via SerialPort, write to an array and then to the FIFO buffer.
I’m attaching my code for the same.
namespace SciChart.Examples.Examples.SeeFeaturedApplication.ECGMonitor
{
public class ECGMonitorViewModel : BaseViewModel
{
private Timer _timer;
private IXyDataSeries<double, double> _series0;
public static double[] _sourceData = new double[50000];
private int _currentIndex = 0;
private int _totalIndex = 0;
private DoubleRange _yVisibleRange;
private bool _isBeat;
private int _heartRate;
private bool _lastBeat;
private DateTime _lastBeatTime;
private ICommand _startCommand;
private ICommand _stopCommand;
private const double WindowSize = 5.0;
private const int TimerInterval = 40;
public static int counter = 0;
public static SerialPort mySerialPort=new SerialPort("COM3",9600);
public ECGMonitorViewModel()
{
mySerialPort.Open();
ECGMonitorViewModel.mySerialPort.WriteLine("A");
ECGMonitorViewModel.mySerialPort.WriteLine("F");
_series0 = new XyDataSeries<double, double>() { FifoCapacity = 2460, AcceptsUnsortedData = true };
YVisibleRange = new DoubleRange(-20, 500);
_startCommand = new ActionCommand(OnExampleEnter);
_stopCommand = new ActionCommand(OnExampleExit);
}
public ICommand StartCommand
{
get
{
return _startCommand;
}
}
public ICommand StopCommand
{
get
{
return _stopCommand;
}
}
public IXyDataSeries<double, double> EcgDataSeries
{
get
{
return _series0;
}
set
{
_series0 = value;
OnPropertyChanged("EcgDataSeries");
}
}
public DoubleRange YVisibleRange
{
get
{
return _yVisibleRange;
}
set
{
_yVisibleRange = value;
OnPropertyChanged("YVisibleRange");
}
}
public bool IsBeat
{
get
{
return _isBeat;
}
set
{
if (_isBeat != value)
{
_isBeat = value;
OnPropertyChanged("IsBeat");
}
}
}
public int HeartRate
{
get { return _heartRate; }
set
{
_heartRate = value;
OnPropertyChanged("HeartRate");
}
}
public void OnExampleExit()
{
if (_timer != null)
{
_timer.Stop();
_timer.Elapsed -= TimerElapsed;
_timer = null;
}
}
public void OnExampleEnter()
{
_timer = new Timer(TimerInterval) { AutoReset = true };
_timer.Elapsed += TimerElapsed;
_timer.Start();
}
private void TimerElapsed(object sender, EventArgs e)
{
lock (this)
{
for (int i = 0; i < 10; i++)
{
AppendPoint(250);
}
if ((DateTime.Now - _lastBeatTime).TotalMilliseconds < 120) return;
IsBeat = _series0.YValues[_series0.Count - 3] > 120 ||
_series0.YValues[_series0.Count - 5] > 120 ||
_series0.YValues[_series0.Count - 8] > 120;
if (IsBeat && !_lastBeat)
{
HeartRate = (int)(60.0 / (DateTime.Now - _lastBeatTime).TotalSeconds);
_lastBeatTime = DateTime.Now;
}
}
}
private void AppendPoint(double sampleRate)
{
if (_currentIndex >= _sourceData.Length)
{
_currentIndex = 0;
}
double voltage = _sourceData[_currentIndex];
double time = _totalIndex / sampleRate %10;
if(time==0.00)
{
voltage = double.NaN;
}
_series0.Append(time, voltage);
_lastBeat = IsBeat;
_currentIndex++;
_totalIndex++;
}
public static void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
while (mySerialPort.BytesToRead > 0)
{
int b;
b = mySerialPort.ReadByte();
_sourceData[counter] = b;
counter++;
}
}
}
}
namespace SciChart.Examples.Examples.SeeFeaturedApplication.ECGMonitor
{
public partial class ECGMonitorView : UserControl
{
public ECGMonitorView()
{
InitializeComponent();
ECGMonitorViewModel.mySerialPort.DataReceived += new SerialDataReceivedEventHandler(ECGMonitorViewModel.mySerialPort_DataReceived);
}
}
}
The xaml code is as follows,
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:SciChart.Examples.Examples.SeeFeaturedApplication.ECGMonitor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
xmlns:s3D="http://schemas.abtsoftware.co.uk/scichart3D" xmlns:XamlRasterizer="clr-namespace:SciChart.Drawing.XamlRasterizer;assembly=SciChart.Drawing" x:Class="SciChart.Examples.Examples.SeeFeaturedApplication.ECGMonitor.ECGMonitorView"
d:DesignHeight="400"
d:DesignWidth="600"
mc:Ignorable="d">
<UserControl.Resources>
<Style TargetType="{x:Type s:RenderSurfaceBase}">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="5"
ShadowDepth="0"
Color="#FFB3E8F6" />
</Setter.Value>
</Setter>
</Style>
<local:BeatToScaleConverter x:Key="BeatToScaleConverter" />
</UserControl.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding StartCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="Unoaded">
<i:InvokeCommandAction Command="{Binding StopCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid>
<s:SciChartSurface RenderPriority="Low" MaxFrameRate="25" AutoRangeOnStartup="False">
<s:SciChartSurface.RenderableSeries>
<s:FastLineRenderableSeries DataSeries="{Binding EcgDataSeries}"
Stroke="#FFB3E8F6"
StrokeThickness="2" />
</s:SciChartSurface.RenderableSeries>
<s:SciChartSurface.YAxis>
<s:NumericAxis AxisTitle="Voltage (mV)"
DrawMinorGridLines="True"
MaxAutoTicks="5"
VisibleRange="{Binding YVisibleRange, Mode=TwoWay}" />
</s:SciChartSurface.YAxis>
<s:SciChartSurface.XAxis>
<s:NumericAxis AxisTitle="Seconds (s)" TextFormatting="0.000s" VisibleRange="0, 10" AutoRange="Never"/>
</s:SciChartSurface.XAxis>
<s:SciChartSurface.RenderSurface>
<s3D:Direct3D10RenderSurface/>
</s:SciChartSurface.RenderSurface>
</s:SciChartSurface>
<StackPanel Margin="30,30" Orientation="Horizontal">
<StackPanel.Effect>
<DropShadowEffect BlurRadius="5"
ShadowDepth="0"
Color="#FFB3E8F6" />
</StackPanel.Effect>
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
<Canvas x:Name="layer1"
Width="20"
Height="20"
Margin="12,34,10,0">
<Canvas.RenderTransform>
<ScaleTransform CenterX="-6"
CenterY="-6"
ScaleX="{Binding IsBeat, Converter={StaticResource BeatToScaleConverter}}"
ScaleY="{Binding IsBeat, Converter={StaticResource BeatToScaleConverter}}" />
</Canvas.RenderTransform>
<Path Data="m 0 0 c -4 -4 -8.866933 -10.79431 -10 -15 0 0 0 -5 5 -5 5 0 5 5 5 5 0 0 0 -5 5 -5 5 0 5.242535 4.02986 5 5 -1 4 -6 11 -10 15 z" Fill="#FFB0E6F4" />
</Canvas>
</Grid>
<TextBlock HorizontalAlignment="Left"
VerticalAlignment="Top"
FontFamily="ArialBlack"
FontSize="36"
FontWeight="Bold"
Foreground="#FFB0E6F4"
Text="{Binding HeartRate}" />
<TextBlock HorizontalAlignment="Left"
VerticalAlignment="Top"
FontFamily="ArialBlack"
FontSize="36"
FontWeight="Bold"
Foreground="#FFB0E6F4"
Text="BPM" />
</StackPanel>
<TextBlock Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
FontSize="9"
FontStyle="Italic"
Foreground="#FFB0E6F4"/>
</Grid>
I’ve attached pictures of what my program currently does. I have also attached a file with sample data in case anybody wants to test the program. I have also tried building in release mode and that doesn’t help, either.
The only issue is the delay in plotting of real-time data. Otherwise, the graphing and rendering is really smooth. As I am a complete beginner to this, can somebody help with me with what I might have done wrong?
Thanks a ton,
Jaivignesh Jayakumar
- Jaivignesh Jayakumar asked 8 years ago
- last active 8 years ago