Oscilloscope emulation
-
- Newbie
- Posts: 22
- Joined: Mon Aug 24, 2015 12:00 am
Oscilloscope emulation
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?
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 (93.61 KiB) Viewed 17257 times
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Oscilloscope emulation
A rough mock-up such as the following may offer you some pointers: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?
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);
}
}
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 |
-
- Newbie
- Posts: 22
- Joined: Mon Aug 24, 2015 12:00 am
Re: Oscilloscope emulation
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!
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!
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Oscilloscope emulation
Hello,
Possibly something more like this then: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.
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 |
-
- Newbie
- Posts: 22
- Joined: Mon Aug 24, 2015 12:00 am
Re: Oscilloscope emulation
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!!
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!!
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Oscilloscope emulation
Hello,
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!
This code:Anaesthesia wrote:Here's some code which illustrates the problem more clearly:
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;
}
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 |
-
- Newbie
- Posts: 22
- Joined: Mon Aug 24, 2015 12:00 am
Re: Oscilloscope emulation
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
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
-
- Newbie
- Posts: 22
- Joined: Mon Aug 24, 2015 12:00 am
Re: Oscilloscope emulation
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
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Oscilloscope emulation
Hello Andy,
I notice that you have set:
at designtime, which guarantees that the Color.Transparent (the "null" points) will be ignored and the point painted anyway. Setting this to:
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:
Great, thank you!Anaesthesia wrote: I've attached a working solution which demonstrates the problem and certainly runs on my system.
I notice that you have set:
Code: Select all
this.fastLine.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.Ignore;
Code: Select all
fastLine.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.DoNotPaint;
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 |
-
- Newbie
- Posts: 22
- Joined: Mon Aug 24, 2015 12:00 am
Re: Oscilloscope emulation
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?
-
- Newbie
- Posts: 22
- Joined: Mon Aug 24, 2015 12:00 am
Re: Oscilloscope emulation
Don't worry about the surface plot - I used the example in the evaluation example - it works extremely well...
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Oscilloscope emulation
Excellent, I'm very pleased to hear it.Anaesthesia wrote:Don't worry about the surface plot - I used the example in the evaluation example - it works extremely well...
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 |