2015-04-17 9 views
1

Я разрабатываю научное приложение в Windows Forms (VC++ 2010), которое управляет относительно новым электронным устройством. Я управляю им дополнительной, завернутой библиотекой, написанной на C. После первоначальной настройки всех параметров это приложение запускает измерение в устройстве. Затем он отправляет в мое приложение огромные данные из более 200 тыс. Выборок int с существенной скоростью - предположим, что это 50 наборов данных в секунду.Эффективный способ сокращения данных для графика в реальном времени

Теперь мне нужно построить мои данные в реальном времени, используя диаграмму Windows Forms. Было бы идеально иметь 750 образцов, построенных внутри диаграммы со скоростью около 30 FPS. Проблема, с которой я столкнулся, заключается в алгоритме быстрого восстановления базы данных без потери надежности графика.

Мои идеи (данные oscilating вокруг значения = 127):

  1. Выберите 750 баллов, просто выбрав каждый (200 000/750) -й точки

  2. Группа данных и расчета среднего значения

  3. Группируйте данные и выберите максимум или минимум (в зависимости от общего размещения в группе - если большинство из них выше 127 - выберите минимальный, другой максимум).

Какой один (если таковые имеются) из тех, решение является наилучшим учитывая, что я должен построить данные на скорости в режиме реального времени и сюжета не должны пропустить пятна, где мы имеем какой-либо значительный сигнал (похожий на вид сужен , модулированная синусоидальная волна)? Есть ли лучший подход?

И последний вопрос: следует ли использовать таблицу указателей для моего огромного буфера данных или копии данных как данные для графика, учитывая, что у меня всегда есть тот же буфер собранных данных (устройство просто перезаписывает этот буфер постоянно новыми данными)?

Это мой первый пост, поэтому, пожалуйста, сообщите мне, если что-то не так в стиле сообщения.

ответ

1

Я разработал приложение, которое считывает данные с частотой 256 Гц (256 выборок в секунду) из 16 каналов и отображает его в 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); 
      } 
     } 
} 
Смежные вопросы