Profile Picture

Real time line chart with auto-scroll

Posted By Janosch Peters 15 Years Ago
Author
Message
Janosch Peters
Posted 15 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)

Group: Forum Members
Last Active: 15 Years Ago
Posts: 4, Visits: 1

Hi,

Id like to develope a real time line chart which updates its view range as soon as new data points are outside the view range. The chart is used to show measurement values over time. So each Datapoint is a (value/timestamp) pair.

I tried to achieve this by modifying the "Stretch Margin Mode" example, but I'm stuck at multiple issues:

1. The labels on the time axis should be formatted like mm:ss:msmsms. How do I do that?

2. How do I set the range to show values from "00:00:000" to, for example "00:03:000"? I tried NRange1DD but what unit are those double values? How do I convert a time span to those range values?

3. If I add a XValue to a line chart, how do I know wether it is within the view range?

4. Can I assign multiple line charts to one y-axis?

I attached the example with my code changes (there are only a few).



Attachments
NStretchMarginModeUC.cs (38 views, 22.00 KB)
bob milanov
Posted 15 Years Ago
View Quick Profile
Supreme Being

Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)

Group: Forum Members
Last Active: 6 Months Ago
Posts: 153, Visits: 11

Hi Janosch,

First of all thank you for your interest in Nevron Chart for .NET.

Probably the example distributed with the component is not the best way to start this project. I've modified the code without the embellishments in the example:

public partial class Form1 : Form
{
public NLineSeries m_Line1;
public NLineSeries m_Line2;
public int m_nCounter = 0;
public Random m_Random = new Random();

public Form1()
{
InitializeComponent();
}

private void timer1_Tick(object sender, EventArgs e)
{
// feed random value for line 1 and 2
double fIndicator1 = Math.Sin(m_nCounter * 10 * 3.14 / 180) * 100 * (m_Random.NextDouble() + 1.0);
double fIndicator2 = Math.Cos(m_nCounter * 10 * 3.14 / 180) * 100 * (m_Random.NextDouble() + 1.0);
m_Line1.Values.Add(fIndicator1);
m_Line2.Values.Add(fIndicator2);

DateTime now = DateTime.Now;
m_Line1.XValues.Add(now.ToOADate());
m_Line2.XValues.Add(now.ToOADate());

// delete everything which is older than ten seconds one minute
TimeSpan span = new TimeSpan(0, 0, 10);
NRange1DD range= new NRange1DD((now - span).ToOADate(), now.ToOADate());

int count = m_Line1.Values.Count;
for (int i = (count - 1); i >= 0; i--)
{
double xVal = (double)m_Line1.XValues[i];
if (!range.Contains(xVal))
{
m_Line1.Values.RemoveAt(i);
m_Line1.XValues.RemoveAt(i);
m_Line2.Values.RemoveAt(i);
m_Line2.XValues.RemoveAt(i);
}
}
m_nCounter++;
nChartControl1.Refresh();
}

private void StartStopTimerButton_Click(object sender, EventArgs e)
{
if (StartStopTimerButton.Text.StartsWith("Start"))
{
StartStopTimerButton.Text =
"Stop Timer";
timer1.Start();
}
else
{
StartStopTimerButton.Text =
"Start Timer";
timer1.Stop();
}
}

private void Form1_Load(object sender, EventArgs e)
{
nChartControl1.Panels.Clear();

// create a chart
NCartesianChart chart = new NCartesianChart();
chart.Margins =
new NMarginsL(10, 10, 10, 10);
chart.Dock =
DockStyle.Fill;
chart.BoundsMode =
BoundsMode.Stretch;
chart.Wall(
ChartWallType.Left).Width = 0.0f;
nChartControl1.Panels.Add(chart);

// set the Y axis range to be from -200 to 200
chart.Axis(StandardAxis.PrimaryY).View = new NRangeAxisView(new NRange1DD(-200, 200));

NDateTimeScaleConfigurator scaleConf = new NDateTimeScaleConfigurator();
scaleConf.EnableUnitSensitiveFormatting =
false;

// disable tick rounding
scaleConf.RoundToTickMax = false;
scaleConf.RoundToTickMin =
false;

// change formatting to minute:second
scaleConf.LabelValueFormatter = new NDateTimeValueFormatter("mm:ss");

chart.Axis(StandardAxis.PrimaryX).ScaleConfigurator = scaleConf;
chart.Axis(
StandardAxis.Depth).Visible = false;

// add the first line
m_Line1 = (NLineSeries)chart.Series.Add(SeriesType.Line);
m_Line1.UseXValues =
true;
m_Line1.Name =
"Realtime indicator 1";
m_Line1.MultiLineMode =
MultiLineMode.Series;
m_Line1.DataLabelStyle.Visible =
false;
m_Line1.Values.ValueFormatter =
new NNumericValueFormatter("0.0");
m_Line1.BorderStyle.Color =
Color.DarkOrange;
m_Line1.BorderStyle.Width =
new NLength(2, NGraphicsUnit.Pixel);
m_Line1.FillStyle =
new NColorFillStyle(Color.DarkOrange);

// add the second line
m_Line2 = (NLineSeries)chart.Series.Add(SeriesType.Line);
m_Line2.UseXValues =
true;
m_Line2.Name =
"Realtime indicator 2";
m_Line2.MultiLineMode =
MultiLineMode.Series;
m_Line2.DataLabelStyle.Visible =
false;
m_Line2.Values.ValueFormatter =
new NNumericValueFormatter("0.0");
m_Line2.BorderStyle.Color =
Color.LimeGreen;
m_Line2.BorderStyle.Width =
new NLength(2, NGraphicsUnit.Pixel);
m_Line2.FillStyle =
new NColorFillStyle(Color.LimeGreen);
}

A few comments:

1. If you're going to use XValues in the series you also have to specify this in the line series (m_Line1.UseSeries = true)
2. The code disables unit sensitive formatting and instead installs a simple value formatter that will show only minute:second part of the date time stamp (generated by the current time on the timer tick):

scaleConf.EnableUnitSensitiveFormatting = false;

// disable tick rounding
scaleConf.RoundToTickMax = false;
scaleConf.RoundToTickMin =
false;

// change formatting to minute:second
scaleConf.LabelValueFormatter = new NDateTimeValueFormatter("mm:ss");

3. The ToOADate function converts a date time value to its double equivalent. The function abbreviation stands for "To Ole Automation Date" (a format introduced back in the COM world).

Regarding your questions:

1. The labels on the time axis should be formatted like mm:ss:msmsms. How do I do that?
See above.

2. How do I set the range to show values from "00:00:000" to, for example "00:03:000"? I tried NRange1DD but what unit are those double values? How do I convert a time span to those range values?

3. If I add a XValue to a line chart, how do I know wether it is within the view range?
Technically it is not possible to use a date time value stamp with time span as the span itself does not relate to a date - you can however limit the range of the current view by deleting points that do not fall in this range - in the above code this is achieved by filtering all data points that do not fall in the time range [now - 10 seconds, now].

4. Can I assign multiple line charts to one y-axis?
By default all series will scale on the PrimaryY axis. You can also change that by setting series to scale to the SecondaryY axis or a custom axis.

Hope this helps - let me know if you meet any problems...

Best regards,
Bob

 



Janosch Peters
Posted 15 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)

Group: Forum Members
Last Active: 15 Years Ago
Posts: 4, Visits: 1

Thanks Bob. I already started from scratch but I stuck on the same issues and your answers were very helpful.

I think ToOADate should be mentioned in the NRange1DD documentation. I think pretty much everybody who wants a timeline range would be stuck here. Even nicer would be a constructer like NRange1DD( TimeDate start, TimeDate end).

The chart now looks almost as I like, except of the following:

- The time format should be "mm:ss:msmsmsms", with "min" as a suffix. Should be an easy task, but sadly the formatSpecifier in NDateTimeValueFormatter Constructor doesent seem to be documented.

- How do I enforce a major tick mark with a lable at the beginning and at the end of the range (in the same format as mentioned above)?

- Does nevron provide sth like a crosshair, which you can slide along the curve and hops from XValue to XValue and displays the y-value / x-value (see the screen shot)? If not, can you point me to some nevron methods / classes which you think might be helpful to implement this?

BTW, is there a way attach images to a post? I wanted to provide a screenshot here, but the forum didnt let me.

[EDIT]

- Is OpenGL in Window mode considered to be the fastest rendering method? Speed is very crucial for us and will be one of the key criteria for chosing our graphing sdk.

[EDIT2]

- The BackColor propertie of NChartControl seems to be ignored. My backcolor is always white.

- The BackgroundImage propertie of NChartControl has a strange behavior

1. If I specify a 1x1 grey bmp file as a resource and set "tile" as display mode, I get a color gradient from grey to black. Note that BackColor is set to white at the same time.

2. If I want to unset the background image to "none" I get a property error, telling me that none is not a valid selection. I have to go into the designer code and remove the line myself.



Attachments
StripChartTestFW.Designer.cs (42 views, 8.00 KB)
StripChartTestFW.cs (39 views, 7.00 KB)
bob milanov
Posted 15 Years Ago
View Quick Profile
Supreme Being

Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)Supreme Being (152 reputation)

Group: Forum Members
Last Active: 6 Months Ago
Posts: 153, Visits: 11

Hi Janosch,

 

1. I think ToOADate should be mentioned in the NRange1DD documentation. I think pretty much everybody who wants a timeline range would be stuck here. Even nicer would be a constructer like NRange1DD( TimeDate start, TimeDate end).

 

It is part of the .NET framework class DateTime, and is well documented. Check out the following topic in MSDN: http://msdn.microsoft.com/en-us/library/system.datetime.tooadate.aspx.

 

2. The time format should be "mm:ss:msmsmsms", with "min" as a suffix. Should be an easy task, but sadly the formatSpecifier in NDateTimeValueFormatter Constructor doesn’t seem to be documented.

 

The control uses standard .NET date/time formatting with a few extensions and predefined formats. A complete list on how .NET formats dates can be found here:

http://msdn.microsoft.com/en-us/library/97x6twsz.aspx

 

You can use the following format string "mm:ss:fff". Again take a look at the above topic related to formatting.

 

3. Does Nevron provide sth like a crosshair, which you can slide along the curve and hops from XValue to XValue and displays the y-value / x-value (see the screen shot)? If not, can you point me to some Nevron methods / classes which you think might be helpful to implement this?

 

Yes - you can take a look at the following example shipped with the component - Interactivity\Tools\Data Cursor Tool

 

4. BTW, is there a way attach images to a post? I wanted to provide a screenshot here, but the forum didn’t let me.

 

I think it only allows for jpgs...

 

5. Is OpenGL in Window mode considered to be the fastest rendering method? Speed is very crucial for us and will be one of the key criteria for choosing our graphing sdk.

 

Yes - but you can also improve gdi by turning antialiasing off.


nChartControl1.Settings.ShapeRenderingMode = ShapeRenderingMode.None;
nChartControl1.Settings.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;


6. The BackColor propertie of NChartControl seems to be ignored. My backcolor is always white.
7. The BackgroundImage propertie of NChartControl has a strange behavior

 

You should use the BackgroundStyle property of the control. The above two are inherited from the Control and are not used:

nChartControl1.BackgroundStyle.FillStyle = new NColorFillStyle(Color.Red);

 

8. How do I enforce a major tick mark with a label at the beginning and at the end of the range (in the same format as mentioned above)?

 

You can use custom ticks, but that way you'll have to specify all the ticks. Alternatively you can use custom scale programming and create a custom tick/label decorator. If you want to go that way I can show you how to achieve this...

 

Hope I helped - let me know if you have any questions or meet any problems.

 

Best regards,
Bob



Janosch Peters
Posted 15 Years Ago
View Quick Profile
Forum Newbie

Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)Forum Newbie (4 reputation)

Group: Forum Members
Last Active: 15 Years Ago
Posts: 4, Visits: 1

Hi Bob,

1. I think ToOADate should be mentioned in the NRange1DD documentation...

 

It is part of the .NET framework class DateTime, and is well documented. Check out the following topic in MSDN: http://msdn.microsoft.com/en-us/library/system.datetime.tooadate.aspx.

 

True. But how should I know that I have to convert my DateTime to a double. Other SDKs allow to set a range with DateTime objects. And how should I know that I have to use ToOADate. I dont want to split hairs here, just want to tell yout that your docs are not as clear and easy to understand as they could be.

 

2. The time format should be "mm:ss:msmsmsms", with "min" as a suffix. Should be an easy task, but sadly the formatSpecifier in NDateTimeValueFormatter Constructor doesn’t seem to be documented.

 

The control uses standard .NET date/time formatting with a few extensions and predefined formats. A complete list on how .NET formats dates can be found here:

http://msdn.microsoft.com/en-us/library/97x6twsz.aspx

 

Its good that nevron uses standard .NET formatting, however IMHO a good documentation should mention this whenever it is apropriate. A quick hint in NDateTimeValueFormatter(String) would have saved me some time.

 

[EDIT]

Your hint with "mm:ss:fff" doesent work for me. I just set the LabelValueFormatter property of the ScaleConfigurator. Do I have to do sth more?

 

Thanks for the rest of the answers. They are very helpful.





Similar Topics


Reading This Topic