Oscilloscope emulation

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
Post Reply
Anaesthesia
Newbie
Newbie
Posts: 22
Joined: Mon Aug 24, 2015 12:00 am

Oscilloscope emulation

Post by Anaesthesia » Mon Aug 31, 2015 11:48 pm

I'm attempting to emulate 'Oscilloscopic' behaviour of the kind found in ECG Monitors.

The following code snippet is called by a plotting timer every 20 mSecs.

case OpMode.File:
short val;
if (Pressure_Data.TryDequeue(out val)) //If data points are available...
{
if (Wave2Graph.Series[0].Count > Wave2Graph.Axes.Bottom.Maximum) //If we have at least one 'screen' full of data
{ Wave2Graph.Series[0].Delete(Wave2GraphCursor); }

Wave2Graph.Series[0].Add(Wave2GraphCursor++, val);

if (Wave2GraphCursor > Wave2Graph.Axes.Bottom.Maximum)
{ Wave2GraphCursor = 0; }
}
if (Wave2GraphCursor % SIZEOFPRESSURERECORD == 0)
{ GetNextDORecord(); } //Get the next sequence of pressure points...
break;

Once 'Axes.Bottom' data points have been drawn, the plotting cursor is decremented to zero, and plotting recommences from the left hand side of the graph. In this manner, the maximum size of the plotted series is constrained to 'Axes.Bottom' datapoints.

Under these circumstances, how do I prevent a line being drawn from the most recently entered point to the next point in the series (as is indicated by the red arrow in the attached image)? I've tried add nulls and transparent data points, but can't make it work.

Alternatively, can anyone point me at a working dot.net example of such behaviour?
Attachments
Oscilloscope.png
Oscilloscope.png (93.61 KiB) Viewed 17260 times

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Oscilloscope emulation

Post by Christopher » Tue Sep 01, 2015 9:11 am

Anaesthesia wrote: Under these circumstances, how do I prevent a line being drawn from the most recently entered point to the next point in the series (as is indicated by the red arrow in the attached image)? I've tried add nulls and transparent data points, but can't make it work.

Alternatively, can anyone point me at a working dot.net example of such behaviour?
A rough mock-up such as the following may offer you some pointers:

Code: Select all

    Line series;
    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;
      series = new Line(tChart1.Chart);
    }

    Random rnd = new Random();
    int count = 0;

    private void timer1_Tick_1(object sender, EventArgs e)
    {
      for (int i = 0; i < 10; i++)
      {
        series.Add(count, rnd.NextDouble());
        count++;
      }
      
      series.Add(count, 0, Color.Transparent);
      count++;

      for (int i = 0; i < 10; i++)
      {
        series.Add(count, rnd.NextDouble());
        count++;
      }

      tChart1.Axes.Bottom.SetMinMax(count - 20, count -1);

      if (series.Count > 100)
      {
        series.Delete(0, 50);
      }
    }
does this help?
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Anaesthesia
Newbie
Newbie
Posts: 22
Joined: Mon Aug 24, 2015 12:00 am

Re: Oscilloscope emulation

Post by Anaesthesia » Wed Sep 02, 2015 10:02 pm

Dear Christopher,

Thank you for your prompt reply. What you suggest doesn't emulate the behaviour of an ECG monitor (in particular, I don't want the X axis to scroll). In order for it to work, I need to be able to change the Y value of an existing X value in a series and also to change its color (transparency) once the first scan of the monitor's width has been completed.

As a work-around, I create two series for each physiological variable ('Odd' and 'Even') and toggle between them at the end of every monitor scan cycle.

Whenever a value is added to the 'ActiveSeries', the corresponding point is deleted fro the 'InactiveSeries'. Thus the relevant plotting snippet is:

Wave2Graph.Series[ActiveSeries].Add(Wave2GraphCursor++, val);
if (Wave2GraphCursor > Wave2Graph.Axes.Bottom.Maximum)
{
ActiveSeries = (ActiveSeries == 0) ? 1 : 0;
InactiveSeries = (InactiveSeries == 0) ? 1 : 0;
Wave2GraphCursor = 0;
}
if (Wave2Graph.Series[InactiveSeries].Count > 0) Wave2Graph.Series[InactiveSeries].Delete(0);

Although it seems to work well, it seems to be rather inelegant!

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Oscilloscope emulation

Post by Christopher » Thu Sep 03, 2015 7:52 am

Hello,
Anaesthesia wrote:In order for it to work, I need to be able to change the Y value of an existing X value in a series and also to change its color (transparency) once the first scan of the monitor's width has been completed.
Possibly something more like this then:

Code: Select all

    Line series;
    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;
      series = new Line(tChart1.Chart);
      series.FillSampleValues(21);
    }

    Random rnd = new Random();

    private void timer1_Tick_1(object sender, EventArgs e)
    {
      int count = series.Count;

      for (int i = 0; i < count; i++)
      {
        if(i == 10)
        {
          series[i].Y = 0;
          series[i].Color = Color.Transparent;
        }
        else
        {
          series[i].Y = rnd.NextDouble();
        }
      }
    }
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Anaesthesia
Newbie
Newbie
Posts: 22
Joined: Mon Aug 24, 2015 12:00 am

Re: Oscilloscope emulation

Post by Anaesthesia » Thu Sep 03, 2015 8:26 pm

I'm afraid that his solution doesn't work either. Here's some code which illustrates the problem more clearly:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Random rnd = new Random();
int cursor;
public Form1()
{
InitializeComponent();
tChart1.Aspect.View3D = false;
}

private void timer1_Tick_1(object sender, EventArgs e)
{
if (fastLine1.Count == tChart1.Axes.Bottom.Maximum)
{
fastLine1[cursor].Y = rnd.NextDouble();
fastLine1[cursor].Color = Color.Transparent;
fastLine1[cursor + 1].Y = -1;
fastLine1[cursor + 1].Color = Color.Transparent;
cursor++;
}
else
{
fastLine1.Add(rnd.NextDouble());
cursor++;
}
cursor = (cursor < tChart1.Axes.Bottom.Maximum) ? cursor++ : 0;
}
}
}

This code cycles across the scan correctly, but what I need to happen is for no line to be drawn to a Y value point if it is -1.

Finally, given that I can achieve the result I want by 'toggling' alternate series, I'd be quite happy to admit defeat!!

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Oscilloscope emulation

Post by Christopher » Fri Sep 04, 2015 8:16 am

Hello,
Anaesthesia wrote:Here's some code which illustrates the problem more clearly:
This code:

Code: Select all

    FastLine fastLine1;
    int cursor;
    Random rnd = new Random();

    private void InitializeChart()
    {
      tChart1.Aspect.View3D = false;
      fastLine1 = new FastLine(tChart1.Chart);
      //fastLine1.FillSampleValues();
    }


    private void timer1_Tick(object sender, EventArgs e)
    {
      if (fastLine1.Count == tChart1.Axes.Bottom.Maximum)
      {
        fastLine1[cursor].Y = rnd.NextDouble();
        fastLine1[cursor].Color = Color.Transparent;
        fastLine1[cursor + 1].Y = -1;
        fastLine1[cursor + 1].Color = Color.Transparent;
        cursor++;
      }
      else
      {
        fastLine1.Add(rnd.NextDouble());
        cursor++;
      }
      cursor = (cursor < tChart1.Axes.Bottom.Maximum) ? cursor++ : 0;
    }
gives me an exception when run "as-is", but when I comment in the FillSampleValues the code in the if(), the code that sets transparent colors, is never called. Could you please tweak it for me so I can reproduce the issue here? Thank you!
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Anaesthesia
Newbie
Newbie
Posts: 22
Joined: Mon Aug 24, 2015 12:00 am

Re: Oscilloscope emulation

Post by Anaesthesia » Fri Sep 04, 2015 9:47 pm

Dear Christopher,

I've attached a working solution which demonstrates the problem and certainly runs on my system.

The only file missing (because of upload restrictions) is the TeeChart DLL - which I compiled from the latest source of Teechart4.5.

All the best,

Andy
Attachments
WindowsFormsApplication1.zip
(52.22 KiB) Downloaded 726 times

Anaesthesia
Newbie
Newbie
Posts: 22
Joined: Mon Aug 24, 2015 12:00 am

Re: Oscilloscope emulation

Post by Anaesthesia » Sat Sep 05, 2015 10:12 pm

ScreenCursorExample.png
ScreenCursorExample.png (225.18 KiB) Viewed 17166 times
PostScript:

Here's a screenshot from my application where the 'Scan Cursor' (Arrowed in red') is working correctly. The scan cursor width in this case is 10 pixels, and appears as a black gap. The effect is achieved by toggling odd and even scan series as 'Active' and 'Inactive' and deleting points from the inactive series while drawing to the active series.

Notwithstanding these difficulties, I'm totally impressed with TeeChart!! - As you can probably gather from the screenshot, I'm able to plot thousands of data points per second - while performing FFT's on the waveform at 2 Hz!

Next week, I hope to start migrating the app from this PC version to a Xamarin implementation. Can you point me at any examples which demonstrate very fast plotting (particularly on Android devices)?

Thank you again,

Andy

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Oscilloscope emulation

Post by Christopher » Mon Sep 07, 2015 8:49 am

Hello Andy,
Anaesthesia wrote: I've attached a working solution which demonstrates the problem and certainly runs on my system.
Great, thank you!

I notice that you have set:

Code: Select all

this.fastLine.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.Ignore;
at designtime, which guarantees that the Color.Transparent (the "null" points) will be ignored and the point painted anyway. Setting this to:

Code: Select all

fastLine.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.DoNotPaint;
causes all the points to become null! This, in fact, is expected in the code you send - as soon as the series is full of points (i.e. tChart1.Series[0].Count == tChart1.Axes.Bottom.Maximum) *all* the points are set to null points. Maybe this is not your intention. I suspect that you want the null point to move across the series as new points are added, in which case you could try:

Code: Select all

    public Form1()
    {
      InitializeComponent();
      tChart1.Axes.Left.SetMinMax(-2, 3);

      fastLine.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.DoNotPaint;
    }

    private void timer1_Tick_1(object sender, EventArgs e)
    {

      if (tChart1.Series[0].Count == tChart1.Axes.Bottom.Maximum) //If we've accumulated at least 1 scan...
      {
        tChart1.Series[0][cursor].Y = rnd.NextDouble();
        tChart1.Series[0][cursor].Color = tChart1.Series[0].Color;
        tChart1.Series[0][cursor + 1].Color = Color.Transparent;

      }
      else
      {
        tChart1.Series[0].Add(rnd.NextDouble());
      }
      cursor++;
      cursor = (cursor < tChart1.Axes.Bottom.Maximum) ? cursor : 0;
    }
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Anaesthesia
Newbie
Newbie
Posts: 22
Joined: Mon Aug 24, 2015 12:00 am

Re: Oscilloscope emulation

Post by Anaesthesia » Mon Sep 07, 2015 8:20 pm

:D
Dear Christopher,

Perfect!! – In all the excitement I missed the “Steema.TeeChart.Styles.TreatNullsStyle.Ignore” property!

I now need to display the two-dimensional frequency spectrum shown in the lower chart in the image above on a 3D surface chart.

The application performs the FFT @ 2Hz. After each transformation the magnitudes of each frequency are accumulated into an array (dimensions double[100]) – where each element of the array represents a frequency range (‘bin’) (X value) and the value contained within the element is the sum of all magnitudes within this frequency range (Y value).

Essentially, I now want to add a ‘Z’ axis (Time) by drawing my double array at 2Hz onto a surface chart such that each time a new FFT array is accumulated, it will be added to the chart with a Z value which had been incremented by 500 mSec (0.5 Hz).

Can you point me at a code snippet which demonstrates the addition of such numerical arrays to a surface plot?

Regards,
Andy
PS Should I start this as a new topic?

Anaesthesia
Newbie
Newbie
Posts: 22
Joined: Mon Aug 24, 2015 12:00 am

Re: Oscilloscope emulation

Post by Anaesthesia » Tue Sep 08, 2015 1:37 am

Don't worry about the surface plot - I used the example in the evaluation example - it works extremely well...

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Oscilloscope emulation

Post by Christopher » Tue Sep 08, 2015 7:53 am

Anaesthesia wrote:Don't worry about the surface plot - I used the example in the evaluation example - it works extremely well...
Excellent, I'm very pleased to hear it.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Post Reply