Adding some more data to chart , every time when timer runs (Join, or Concat)

Apr 21, 2009 at 9:03 AM

Hi,

Will this chart supports real time application

I am developing some real time chart application. In this I am trying to do some thing like

Adding (trying to add) data dynamically in timer

 

//Private

const int N = 180;

double[] y = new double[N];

DateTime[] date = new DateTime[N];

LineGraph chart;

Random rand = new Random();

EnumerableDataSource<double> ys;

EnumerableDataSource<DateTime>  xs;

CompositeDataSource ds;

DispatcherTimer timer = new DispatcherTimer();

 

//Initialize

void Window1_Loaded(object sender, RoutedEventArgs e)

{

for (int i = 0; i < N; i++)

{

y[i] = rand.Next();

      date[i] = DateTime.Now.AddMinutes(-N + i);

}

 

ys = new EnumerableDataSource<double>(y);

ys.SetYMapping(_y => _y);

xs = new EnumerableDataSource<DateTime>(date);

xs.SetXMapping(dateAxis.ConvertToDouble);

ds = new CompositeDataSource(xs, ys);

chart = plotter.AddLineGraph(ds1,Color.FromRgb(0,0,255),1,"Test");

 

timer.Tick += OnTimerTick;   

      timer.Start();

timer.Interval = new TimeSpan(0, 0, 1);

}

 

private void OnTimerTick(object sender, EventArgs e)

{

      TimeSpan ts = DateTime.Now.Subtract(endtime);

      int n = (int)ts.TotalSeconds;

      double[] y1 = new double[n];

 

      DateTime[] date1 = new DateTime[n];

      Random rand = new Random();

for (int i = 0; i < n; i++)

{

Y1[i] = rand.Next();

            Date1[i] = DateTime.Now.AddMinutes(-n + i);

}

 

EnumerableDataSource<double> ys1 = new EnumerableDataSource<double>(y1);

EnumerableDataSource<DateTime>  xs1 = new  EnumerableDataSource<DateTime>(date1);

 

xs.Join(xs1); // No change

ys.Join(ys1); // No change

 

ds.DataParts.Concat<CompositeDataSource>((CompositeDataSource)ds1); //Compilation error

}

 

//I saw few properties like “Join” “Concat”, I tried to use these properties, But it didn’t work for me.

 

 As I read in some forum, I tried to use

 

using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;

 

I tried to use the following statements in timer, with these I got the result (with few lines of code change), But this is taking lot of CPU utilization

 

plotter.Children.Remove(chart);

chart = plotter.AddLineGraph(ds1, Color.FromRgb(0,0,255),1,"Test");

 

It would be very nice if you give some solution how to Add or Concat  two CompositeDataSource etc.

 

Regards
Ravi.

Apr 21, 2009 at 2:05 PM
Hi Ravi,

For real time application see the following code.

This is an extract from the Simulation Sample in the first release of DDD.
Don't ask me, I don't know why this sample was not available in the 2nd release :)

In a word, You should use the AppendAsync method.

I hope it will help you.

Kamel


PS: How do you manage to post some code with the color? When I do a copy / paste from from VS it doesn't work. Colors are funny...




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using System.Globalization;
using System.Reflection;
using System.IO;

namespace Simulation
{
    
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        // Three observable data sources. Observable data source contains
        // inside ObservableCollection. Modification of collection instantly modify
        // visual representation of graph.
        ObservableDataSource<Point> source1 = null;
        ObservableDataSource<Point> source2 = null;
        ObservableDataSource<Point> source3 = null;

        public Window1()
        {
            InitializeComponent();
        }

        private void Simulation()
        {
            CultureInfo culture = CultureInfo.InvariantCulture;
            Assembly executingAssembly = Assembly.GetExecutingAssembly();
            // load spim-generated data from embedded resource file
            const string spimDataName = "Simulation.Repressilator.txt";
            using (Stream spimStream = executingAssembly.GetManifestResourceStream(spimDataName))
            {
                using (StreamReader r = new StreamReader(spimStream))
                {
                    string line = r.ReadLine();
                    while (!r.EndOfStream)
                    {
                        line = r.ReadLine();
                        string[] values = line.Split(',');

                        double x = Double.Parse(values[0], culture);
                        double y1 = Double.Parse(values[1], culture);
                        double y2 = Double.Parse(values[2], culture);
                        double y3 = Double.Parse(values[3], culture);

                        Point p1 = new Point(x, y1);
                        Point p2 = new Point(x, y2);
                        Point p3 = new Point(x, y3);

                        source1.AppendAsync(Dispatcher, p1);
                        source2.AppendAsync(Dispatcher, p2);
                        source3.AppendAsync(Dispatcher, p3);

                        

                        //Thread.Sleep(10); // Long-long time for computations...
                    }
                }
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Create first source
            source1 = new ObservableDataSource<Point>();
            // Set identity mapping of point in collection to point on plot
            source1.SetXYMapping(p => p);

            // Create second source
            source2 = new ObservableDataSource<Point>();
            // Set identity mapping of point in collection to point on plot
            source2.SetXYMapping(p => p);

            // Create third source
            source3 = new ObservableDataSource<Point>();
            // Set identity mapping of point in collection to point on plot
            source3.SetXYMapping(p => p);

            // Add all three graphs. Colors are not specified and chosen random
            plotter.AddLineGraph(source1, 2, "Data row 1");
            plotter.AddLineGraph(source2, 2, "Data row 2");
            plotter.AddLineGraph(source3, 2, "Data row 3");

            // Force everyting to fit in view
            plotter.Viewport.FitToView();

            // Start computation process in second thread
            Thread simThread = new Thread(new ThreadStart(Simulation));
            simThread.IsBackground = true;
            simThread.Start();
        }
    }
}

Apr 21, 2009 at 3:50 PM
Hi,

PS: How do you manage to post some code with the color? When I do a copy / paste from from VS it doesn't work. Colors are funny...


I don't know excatly.

I copided code in word. I did some modification to the content in word.

Then I pasted here, It came with colors.

Regards
Ravi
Editor
Apr 22, 2009 at 10:27 AM
Hi, Kamel and Ravi!

Thank you, Kamel, seems like you've given right answer :)

About SimulationSample - it was deleted from release 0.2 and next by a mistake, and it will be returned to samples. Again, thank you!

P.S.: I'm using http://www.jtleigh.com/people/colin/software/CopySourceAsHtml/ extension for Visual Studio to copy source code as HTML.

Regards,
Mikhail Brinchuk,
DynamicDataDisplay Dev team.
Apr 22, 2009 at 11:09 AM
Hi both Kamel, Mikhail

Thanks for the reply, Its working.
I tested it with some sample application.

Regards
Ravi.
Apr 22, 2009 at 4:32 PM

Hi

thank you very much for you all disscussed this question, and thank you kawone that you post this  Simulation Sample which i couldnt have it from this new release, 

But there is a problem when i use Kawone's code, just simply copy past to my own .cs file, and there is an error when it prepare UI,it says Value cannot be null.
Parameter name: stream
at this   using (StreamReader r = new StreamReader(spimStream)) code. is that missing some stream in the Simulation Sample folder you didnt specify it?

Can you please let me know as i really want to implement this display in real time function,

thank you

Tao

Apr 22, 2009 at 6:35 PM
Edited Apr 22, 2009 at 6:36 PM
Hi,

The following should help.

XAML code:

<Window x:Class="ddd_LiveSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="http://research.microsoft.com/DynamicDataDisplay/1.0"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <my:ChartPlotter Margin="12,12.02,12,41" Name="plotter" >
        <my:ChartPlotter.HorizontalAxis>
            <my:HorizontalDateTimeAxis Name="dateAxis"/>
        </my:ChartPlotter.HorizontalAxis>
        </my:ChartPlotter>
        <Button Height="23" Margin="98,0,80,12" Name="button1" VerticalAlignment="Bottom" Click="button1_Click">Begin Simulation!</Button>
    </Grid>
</Window>



C# code:

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Linq;

    4 using System.Text;

    5 using System.Windows;

    6 using System.Windows.Controls;

    7 using System.Windows.Data;

    8 using System.Windows.Documents;

    9 using System.Windows.Input;

   10 using System.Windows.Media;

   11 using System.Windows.Media.Imaging;

   12 using System.Windows.Navigation;

   13 using System.Windows.Shapes;

   14 using Microsoft.Research.DynamicDataDisplay;

   15 using Microsoft.Research.DynamicDataDisplay.DataSources;

   16 using System.Threading;

   17 

   18 namespace ddd_LiveSample

   19 {

   20     /// <summary>

   21     /// Interaction logic for Window1.xaml

   22     /// </summary>

   23     public partial class Window1 : Window

   24     {

   25         private ObservableDataSource<Trade> _source;

   26         private Random _Random;

   27 

   28         public Window1()

   29         {

   30             InitializeComponent();

   31             _Random = new Random();

   32             EditPlotter();

   33         }

   34 

   35 

   36 

   37         public void EditPlotter()

   38         {

   39             _source = new ObservableDataSource<Trade>();

   40 

   41             // Set identity mapping of point in collection to point on plot

   42             _source.SetXMapping(ci => TimeSpan.FromTicks(ci.Date.Ticks).TotalDays);

   43             _source.SetYMapping(p => p.Price);

   44 

   45             dateAxis.ConvertToDouble = dt => TimeSpan.FromTicks(dt.Ticks).TotalDays;

   46             dateAxis.ConvertFromDouble = d => new DateTime(TimeSpan.FromDays(d).Ticks);

   47 

   48 

   49             // Add graph. Colors are not specified and chosen random

   50             plotter.AddLineGraph(_source, 2, "Data row 1");

   51 

   52             // Force everyting to fit in view

   53             plotter.Viewport.FitToView();

   54 

   55         }

   56 

   57         private void button1_Click(object sender, RoutedEventArgs e)

   58         {

   59             Thread thread = new Thread(Simulation);

   60             thread.Start();

   61             thread.IsBackground = true;

   62         }

   63 

   64         private void Simulation()

   65         {

   66             for (int counter = 0; counter < 100; counter++)

   67             {

   68                 Trade trade = new Trade(DateTime.Now, _Random.NextDouble());

   69                 _source.AppendAsync(Dispatcher, trade);

   70 

   71                 Thread.Sleep(100);

   72             }

   73         }

   74 

   75 

   76     }

   77 

   78     public class Trade

   79     {

   80         public DateTime Date { get; set; }

   81         public double Price { get; set; }

   82 

   83 

   84         public Trade(DateTime dateTime, double price)

   85         {

   86             Date = dateTime;

   87             Price = price;

   88         }

   89     }

   90 

   91 

   92 }


Apr 23, 2009 at 9:01 AM
Edited Apr 23, 2009 at 9:07 AM

kawone

Just tried your example, it works fine, very good. but only one thing it wonder me is that possible to make the chart moving when this simulation line goes further, not the one it compress together, in another word, when the simulation line goes more, the chart should start to move in order to keep the line among it self. Like the background is moving, but not the HorizontalDateTimeAxis

just new to this, thanks,

regards

tao

Apr 23, 2009 at 11:38 AM
Hi,

 

 

 

 

 

 

double xMin = this.dateAxis.ConvertToDouble(DateTime.Now.AddMinutes(-20));

double xMax = this.dateAxis.ConvertToDouble(DateTime.Now.AddMinutes(2));

 

Rect visibleRect = new Rect(xMin, -1000000000, xMax - xMin, 4000000000);
this.plotter.Viewport.Visible = visibleRect;

 

This will help you.  Call this part of code, for every 2 minutes. This code will fix chart limits as 22 minutes, initially you the chart with 20 minutes, for 2 minutes you use

AppendAsync method to fill the chart


Regards
Ravi.

Sep 23, 2009 at 4:47 PM

Hi,

Is there a way to do this horizontal 'scrolling' of the chart in a thread-safe manner.  I am updating it in a thread different from the one that has access to the plotter.

Thanks!

Sep 23, 2009 at 5:04 PM

Have it working - thanks anyway.

 

Mar 11, 2011 at 8:23 AM

Hello Guys,

              When I used ObservableDataSource  it works well for me. But the issue is that for me the datasource is a List (List<DateTime> and List<double>) . So as for a dynamically growing data source, when i use ObservableDataSource  , I have to add data to the ObservableDataSource  <DateTime> and ObservableDataSource  <double> when ever the new values is been added to my List<DateTime> and List<double>. And this ends up in duplication of values and ends up in memory issue.

My dataSource looks like this

Parameter object that contains the following....

  •   List<DateTime> // these values are dynamically growing through a different thread
  •    List<double>   // these values are dynamically growing through a different thread

I tried with EnumerableDataSource but this fails in adding new values to the chart (draws all the existing lines,  but when values are getting added to Lists, it shows no change.) I tried some it make it work by calling 'RaiseDataChanged()' for the changed DataSources but no progress!!!! I have noticed in some sample codes that uses 'RingArray' but in my project I have to use 'List', not 'RingArray'

Please advise...