-2

I am trying plot real-time signal, signal vs time, with WPF and C# (Dynamic Data Display); Once a signal is generated, it should be showed up on a plot chart instantly; The signal can be generated very fast (on the order of mili-second (0.001 second)); What would be the best way to do it? Any suggestion is appreciated.Thanks.

EDIT: An example code will be highly appreciated.

Here is what I have tried:

Plot initiation:

#region Constructor
public SignalStatsDisplay()
{
    InitializeComponent();

    plotter.Legend.Remove();

    _initialChildrenCount = plotter.Children.Count;

    int count = plotter.Children.Count;

    //do not remove the initial children
    if (count > _initialChildrenCount)
    {
        for (int i = count - 1; i >= _initialChildrenCount; i--)
        {
            plotter.Children.RemoveAt(i);
        }
    }

    _nColorChannels = 4;

    _lineprofileColor = new Color[4];

    _lineprofileColor[0] = Colors.Transparent;
    _lineprofileColor[1] = Colors.Red;
    _lineprofileColor[2] = Colors.Black;
    _lineprofileColor[3] = Colors.Blue;


    //LineGraph lg = new LineGraph();
    LineAndMarker<MarkerPointsGraph> lg = new LineAndMarker<MarkerPointsGraph>();
    CirclePointMarker pm = new CirclePointMarker { Size = 10, Fill = Brushes.Green };

  //  MarkerPointsGraph mpg = new MarkerPointsGraph();

    if (_nColorChannels > 0)    // plotter init
    {
        _dataX = new List<int[]>();
        _dataY = new List<int[]>();

        int[] dataXOneCh = new int[1];
        int[] dataYOneCh = new int[1];

        dataXOneCh[0] = 0;
        dataYOneCh[0] = 0;

        /*CirclePointMarker marker = new CirclePointMarker();
        marker.Fill = new SolidColorBrush(_lineprofileColor[0]);
        marker.Pen = new Pen(marker.Fill, 0);

        marker.Size = 2;
        int lineWidth = 1;*/




        for (int i = 0; i < 4; i++)
        {
            _dataX.Add(dataXOneCh);    // data x-y mapping init
            _dataY.Add(dataYOneCh);

            EnumerableDataSource<int> xOneCh = new EnumerableDataSource<int>(dataXOneCh);
            EnumerableDataSource<int> yOneCh = new EnumerableDataSource<int>(dataYOneCh);

            xOneCh.SetXMapping(xVal => xVal);
            yOneCh.SetXMapping(yVal => yVal);

            CompositeDataSource dsOneCh = new CompositeDataSource(xOneCh, yOneCh);

           // LineProfileColorSetup();

            lg = plotter.AddLineGraph(dsOneCh,                    
                (new Pen(Brushes.Green, 2)),
                 pm,
                (new PenDescription("Data")));

           // lg = plotter.AddLineGraph(dsOneCh,
           //    Colors.Transparent,
           //    2,
           //    "Data");

          // pm.FilteringEnabled = false;

        }

        plotter.FitToView();
    }
    else
    {
        return;
    }
}

Data update:

 for (int i = 0; i < 1; i++)
                {
                    if (_dataX[i].Length == _dataY[i].Length)
                    {
                        EnumerableDataSource<int> xOneCh = new EnumerableDataSource<int>(_dataX[i]);
                        xOneCh.SetXMapping(xVal => xVal);
                        EnumerableDataSource<int> yOneCh = new EnumerableDataSource<int>(_dataY[i]);
                        yOneCh.SetYMapping(yVal => yVal);
                        CompositeDataSource ds = new CompositeDataSource(xOneCh, yOneCh);

                        Action UpdateData = delegate()
                        {
                           // ((LineGraph)plotter.Children.ElementAt(startIndex + i)).DataSource = ds;
                           // ((LineGraph)plotter.Children.ElementAt(startIndex + i)).LinePen = new Pen(new SolidColorBrush(Colors.Green), 1);
                           // ((PointsGraphBase)plotter.Children.ElementAt(startIndex + i)).DataSource = ds;
                            ((PointsGraphBase)plotter.Children.ElementAt(startIndex + i + 1)).DataSource = ds;

                            //  }
                           // (plotter.Children.ElementAt(startIndex + i)).DataSource = ds; 

                        };

                        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, UpdateData);
                    }
                }

The problem I have is when signal comes in very fats, say a new signal is generated every mili-second, it seems the graph only generate a new marker every 1 second, which I don't understand.

The basic idea is to generate a plotter.AddLineGraph, then only update the DataSource. But it seems not working. So I thought maybe I am on the wrong direction.

I am not a C# or WPF expert. When LineAndMarker does not work as expected, I started doubting. So I am wondering what would be the general way for people to display real-time signal (rapidly changing, time span between samples could be on mili-second) using WPF and C#.

Nick Tsui
  • 524
  • 2
  • 9
  • 29
  • What kind of signal are you talking about? How do you want to generate the signal? Have you any code??? – bash.d Feb 15 '13 at 14:58
  • I am wondering does it matter what kind signal it is? – Nick Tsui Feb 15 '13 at 15:19
  • @NickTsui: It might. If you are trying to add points every ms, then it's going to be pretty difficult to keep up. So the question is, do you need all the data? Could you plot just every *nth* point? Do you need to log all the data? Does all the data need to be kept in memory? – Matt Burland Feb 15 '13 at 15:42
  • @NickTsui: Also, do you need to plot *all* the data? Or just a rolling window? (e.g. the last 5 minutes worth). – Matt Burland Feb 15 '13 at 15:46
  • I would assume I need all the data. If a user would like to zoom in to see a 5 mili-second window, I think I should give the user that option. – Nick Tsui Feb 15 '13 at 16:18

1 Answers1

0

I found where I did wrong. Here is the part where problem happens:

_pxlValAllChan[0, signalIndex] = pxlValue;
                                                DateTime currentTime = DateTime.Now; //has to come from real file: Tiff
                                                TimeSpan timeSpan = currentTime - _startTime;

                                                _timeStampAllChan[0, signalIndex] = Convert.ToInt16(timeSpan.TotalSeconds);


                                                _pxlValOneChan = new int[_signalLength]; // no need to new it every time
                                                _timeStampOneChan = new int[_signalLength];
                                                for (int i = 0; i <= signalIndex; i++)
                                                {
                                                    _pxlValOneChan[i] = _pxlValAllChan[0, i];
                                                    //_timeStampOneChan[i] = _timeStampAllChan[0, i];
                                                    _timeStampOneChan[i] = i;
                                                }

                                                _signalDisplay.SetData(_timeStampOneChan, _pxlValOneChan, 0, true);

My x data was based on time. I basically consider the initiation of program as starting point, then I keep track of time elapse by subtracting starting time with current time. Then the time elapse is saved as x-axis data (see the line that is commented out). And this actually causes problem. When I simple change x-axis data as index, the problem is gone. The graph update pretty fast. Although I have not figure out how I should change the logic to still use time elapse as my x-axis data, but that is the culprit of slow updating on the graph.

Nick Tsui
  • 524
  • 2
  • 9
  • 29