减少实时绘图数据的有效方法
Effective way of reducing data for real-time plot
我正在Windows窗体(VC++2010)中开发科学应用程序,它控制着相对较新的电子设备。我通过用C编写的附加的包装库来控制它。在初始设置所有参数后,这个应用程序会触发设备中的测量。然后,它以显著的速度向我的应用程序发送超过20万个int样本的巨大数据——假设它是每秒50个数据集。
现在,我需要使用Windows窗体图表实时绘制数据。将750个样本以大约30FPS的速率绘制在图表中是完美的。我遇到的问题在于在不损失绘图可靠性的情况下快速缩减数据库的算法。
我的想法(数据围绕值=127振荡):
-
只需选择第(200000/750)点即可选择750点
-
将数据分组并计算平均值
-
将数据分组,然后选择最大值或最小值(基于整体分组位置——如果大多数数据高于127——则选择最小值,否则选择最大值)。
考虑到我必须以实时速度绘制数据,并且绘制不应错过我们有任何重要信号(看起来像一种变窄的调制正弦波)的点,这些解决方案中的哪一个(如果有的话)是最好的?有什么更好的方法吗?
最后一个问题是:考虑到我总是有相同的收集数据缓冲区(设备只是不断地用新数据覆盖这个缓冲区),我是否应该考虑使用指向我巨大数据缓冲区的指针表或数据副本作为绘图数据?
这是我的第一篇帖子,所以如果帖子的风格有什么问题,请通知我。
我开发了一个应用程序,可以从16个通道读取256Hz(256个样本/秒)的数据,并将其显示在16个不同的图表中。实时绘制所有数据的最佳方式是使用单独的线程来更新绘图。以下是可能对您也有用的解决方案(c#中)。
读取新数据时,数据将存储在列表或数组中。由于它是实时数据,时间戳也在这里生成。使用所获取数据的采样率:timeStamp=timeStamp+sampleIdx/sampleRate;
public void OnDataRead(object source, EEGEventArgs e)
{
if ((e.rawData.Length > 0) && (!_shouldStop))
{
lock (_bufferRawData)
{
for (int sampleIdx = 0; sampleIdx < e.rawData.Length; sampleIdx++)
{
// Append data
_bufferRawData.Add(e.rawData[sampleIdx]);
// Calculate corresponding timestamp
secondsToAdd = (float) sampleIdx/e.sampleRate;
// Append corresponding timestamp
_bufferXValues.Add( e.timeStamp.AddSeconds(secondsToAdd));
}
}
然后,创建一个每N毫秒睡眠一次的线程(100毫秒适合我显示2秒的数据,但如果我想显示10秒,我需要将线程的睡眠时间增加到500毫秒)
//Create thread
//define a thread to add values into chart
ThreadStart addDataThreadObj = new ThreadStart(AddDataThreadLoop);
_addDataRunner = new Thread(addDataThreadObj);
addDataDel += new AddDataDelegate(AddData);
//Start thread
_addDataRunner.Start();
最后,更新图表并使线程每N毫秒休眠一次
private void AddDataThreadLoop()
{
while (!_shouldStop)
{
chChannels[1].Invoke(addDataDel);
// Sleeep thread for 100ms
Thread.Sleep(100);
}
}
数据将每100ms 添加到图表中
private void AddData()
{
// Copy data stored in lists to arrays
float[] rawData;
DateTime[] xValues;
if (_bufferRawData.Count > 0)
{
// Copy buffered data in thread-safe manner
lock (_bufferRawData)
{
rawData = _bufferRawData.ToArray();
_bufferRawData.Clear();
xValues = _bufferXValues.ToArray();
_bufferXValues.Clear();
}
for (int sampleIdx = 0; sampleIdx < rawData.Length; sampleIdx++)
{
foreach (Series ptSeries in chChannels[channelIdx].Series)
// Add new datapoint to the corresponding chart (x, y, chartIndex, seriesIndex)
AddNewPoint(xValues[sampleIdx], rawData[sampleIdx], ptSeries);
}
}
}
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 比较C++变量的最有效方法
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 一种将 Dart 中的字节数据转换为 C++ 中的无符号字符*的有效方法?
- 检查两个向量是否并行的最有效方法
- 从浮点数中删除小数部分但保留类型的有效方法
- 传递非泛型函数的最有效方法是什么?
- 按升序打印矢量的所有元素直到它为空而没有重复项的最有效方法是什么?
- 创建字符串数组的有效方法
- 返回一个引用C++中另一个类对象的对象的有效方法
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 从std::map值中获取密钥的有效方法