ASE Home Page Products Download Purchase Support About ASE
ChartDirector General
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Like to know how the Realtimechart
Posted by pramilav on Apr-13-2010 23:34
Hi,

Thanks for providing the great realtime chart.
I would like to know how you are moving the graph from the right to left.

Please help.

Regards,
Pramilav

  Re: Like to know how the Realtimechart
Posted by Peter Kwan on Apr-14-2010 00:37
Hi pramilav,

I assume you are using the Windows Forms version of the Realtime Chart sample code.

The chart never moves. Only the data moves. In the sample code, we move the data by shift the data array one position to the left.

/// <summary>
/// Utility to shift a double value into an array
/// </summary>
private void shiftData(double[] data, double newValue)
{
     for (int i = 1; i < data.Length; ++i)
          data[i - 1] = data[i];
     data[data.Length - 1] = newValue;
}

shiftData(myData0, newValue0);
shiftData(myData1, newValue1);
shiftData(myData2, newValue1);
shiftData(myData3, newValue1);

Hope this can help.

Regards
Peter Kwan

  Re: Like to know how the Realtimechart
Posted by pramilav on Apr-14-2010 19:18
Hi,

Thanks for the reply, i have used ShiftData(). The problem is my graph gets shrinked and after a while the graph lines gets jamed.

Any solution to this.

Regards,
Pramilav

  Re: Like to know how the Realtimechart
Posted by pramilav on Apr-14-2010 19:31
Hi,

Herewith i am attaching the sample image.

Thanks & Regards,
Pramilav

  Re: Like to know how the Realtimechart
Posted by pramilav on Apr-14-2010 19:32
Attachments:
Sorry the attachment is too big.
chartjam-1.zip
chartjam-1.zip

4.68 Kb

  Re: Like to know how the Realtimechart
Posted by Peter Kwan on Apr-15-2010 00:25
Hi pramilav,

Without seeing your code, it is hard to me to diagnose the problem. Is it possible to include the charting part of your code, or email to me at pkwan@advsofteng.net?

Regards
Peter Kwan

  Re: Like to know how the Realtimechart
Posted by pramilav on Apr-15-2010 16:39
Hi,

For filling X axis with timestamps, isit possible for you to provide some example with integer value.

Eg : 1,2,3,4....... in xaxis.

Thanks & Regards,
Pramilav

  Re: Like to know how the Realtimechart
Posted by pramilav on Apr-15-2010 18:31
Attachments:
Hi,

Herewith i am attaching the sample code for reference.
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ChartDirector;

namespace WindowsFormsApplication1
{

    public partial class Form1 : Form
    {
        private const int sampleSize = 10;
        private DateTime[] timeStamps = new DateTime[sampleSize];
        private static double counter ;
        
        private double[] counters = new double[sampleSize];
        private double[] dataSeriesA = new double[sampleSize];
        private double[] dataSeriesB = new double[sampleSize];
        private double[] dataSeriesC = new double[sampleSize];
        private DateTime nextDataTime = DateTime.Now;

        //
        // Controls in the form
        // *** Automatically generated by Windows Form Designer ***
        //
        private System.Windows.Forms.Label topLabel;
        private System.Windows.Forms.RadioButton runPB;
        private System.Windows.Forms.RadioButton freezePB;
        private System.Windows.Forms.Label updatePeriodLabel;
        private System.Windows.Forms.NumericUpDown samplePeriod;
        private System.Windows.Forms.Label alarmThresholdLabel;
        private System.Windows.Forms.NumericUpDown alarmThreshold;
        private System.Windows.Forms.Label simulatedMachineLabel;
        private System.Windows.Forms.Label valueALabel;
        private System.Windows.Forms.Label valueA;
        private System.Windows.Forms.Label valueBLabel;
        private System.Windows.Forms.Label valueB;
        private System.Windows.Forms.Label valueCLabel;
        private System.Windows.Forms.Label valueC;
        private System.Windows.Forms.Panel leftPanel;
        private System.Windows.Forms.Label separator;
        private ChartDirector.WinChartViewer winChartViewer1;
        private System.Windows.Forms.Timer dataRateTimer;
        private System.Windows.Forms.Timer chartUpdateTimer;
        private System.Windows.Forms.ContextMenu rightClickContextMenu;
        private System.Windows.Forms.MenuItem copyMenuItem;
        //private System.ComponentModel.IContainer components;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            counter = 0;
            // Data generation rate
            dataRateTimer.Interval = 20;

            // Chart update rate
            chartUpdateTimer.Interval = (int)samplePeriod.Value;

            // Initialize data buffer. In this demo, we just set the initial state to no data.
           /* for (int i = 0; i < timeStamps.Length; ++i)
                timeStamps[i] = DateTime.MinValue;*/
            /*
            for (int i = 0; i < counters.Length; ++i)
                counters[i] = i;
            */
            // Enable RunPB button
            runPB.Checked = true;

            // Now can start the timers for data collection and chart update
            dataRateTimer.Start();
            chartUpdateTimer.Start();
        }
        private void runPB_CheckedChanged(object sender, System.EventArgs e)
        {
            // Update the colors of the buttons depends on their states
            runPB.BackColor = runPB.Checked ? Color.LightGreen : runPB.Parent.BackColor;
            freezePB.BackColor = freezePB.Checked ? Color.LightGreen : freezePB.Parent.BackColor;

            // Enable chart update if the Run button is active.
            chartUpdateTimer.Enabled = runPB.Checked;
        }

        /// <summary>
        /// Updates the chartUpdateTimer interval if the user selects another interval.
        /// </summary>
        private void samplePeriod_ValueChanged(object sender, System.EventArgs e)
        {
            chartUpdateTimer.Interval = (int)samplePeriod.Value;
        }

        /// <summary>
        /// Updates the threshold value if the user modifies the threshold.
        /// </summary>
        private void alarmThreshold_ValueChanged(object sender, System.EventArgs e)
        {
            winChartViewer1.updateViewPort(true, false);
        }

        /// <summary>
        /// Handler for Right Click/Copy
        /// </summary>
        private void copyMenuItem_Click(object sender, System.EventArgs e)
        {
            // Just copy existing image to the clipboard
            Clipboard.SetDataObject(winChartViewer1.Image, true);
        }

        /// <summary>
        /// The data generator - invoke once every 250ms
        /// </summary>
        private void dataRateTimer_Tick(object sender, System.EventArgs e)
        {
            //do
            {
                // This is our formula for the data generator
                double p = nextDataTime.Ticks / 10000000.0 * 4;
                double dataA = 20 + Math.Cos(p * 129241) * 10 + 1 / (Math.Cos(p) * Math.Cos(p) + 0.01);
                double dataB = 150 + 100 * Math.Sin(p / 27.7) * Math.Sin(p / 10.1);
                double dataC = 150 + 100 * Math.Cos(p / 6.7) * Math.Cos(p / 11.9);
            
               /* double dataA = 20;
                double dataB = 330;
                double dataC = 100;
                */

                // Now we shift the data into the array
                shiftData(dataSeriesA, dataA);
                shiftData(dataSeriesB, dataB);
                shiftData(dataSeriesC, dataC);
                shiftData(counters, counter);
                //shiftData(timeStamps, nextDataTime);
                counter=counter+1;
                // Update nextDataTime
             
                nextDataTime = nextDataTime.AddMilliseconds(dataRateTimer.Interval);
            }
          //  while (nextDataTime < DateTime.Now);

            // We provide some visual feedback to the numbers generated, so you can see the
            // data being updated.
           // valueA.Text = dataSeriesA[dataSeriesA.Length - 1].ToString(".##");
            //valueB.Text = dataSeriesB[dataSeriesB.Length - 1].ToString(".##");
            //valueC.Text = dataSeriesC[dataSeriesC.Length - 1].ToString(".##");
        }

        /// <summary>
        /// Utility to shift a double value into an array
        /// </summary>
        private void shiftData(double[] data, double newValue)
        {
            for (int i = 1; i < data.Length; ++i)
                data[i - 1] = data[i];
            data[data.Length - 1] = newValue;
        }

        /// <summary>
        /// Utility to shift a DataTime value into an array
        /// </summary>
        private void shiftData(DateTime[] data, DateTime newValue)
        {
            for (int i = 1; i < data.Length; ++i)
                data[i - 1] = data[i];
            data[data.Length - 1] = newValue;
        }

        /// <summary>
        /// The chartUpdateTimer Tick event - this updates the chart periodicially.
        /// </summary>
        private void chartUpdateTimer_Tick(object sender, System.EventArgs e)
        {
            winChartViewer1.updateViewPort(true, false);
        }

        /// <summary>
        /// The viewPortChanged event handler.
        /// </summary>
        private void winChartViewer1_ViewPortChanged(object sender, ChartDirector.WinViewPortEventArgs e)
        {
            drawChart(winChartViewer1);
        }

        /// <summary>
        /// Draw the chart and display it in the given viewer.
        /// </summary>
        private void drawChart(WinChartViewer viewer)
        {
            // Create an XYChart object 600 x 270 pixels in size, with light grey (f4f4f4) 
            // background, black (000000) border, 1 pixel raised effect, and with a rounded frame.
            XYChart c = new XYChart(600, 270, 0xf4f4f4, 0x000000, 1);
            c.setRoundedFrame(Chart.CColor(BackColor));

            // Set the plotarea at (55, 62) and of size 520 x 175 pixels. Use white (ffffff) 
            // background. Enable both horizontal and vertical grids by setting their colors to 
            // grey (cccccc). Set clipping mode to clip the data lines to the plot area.
            c.setPlotArea(55, 62, 520, 175, 0xffffff, -1, -1, 0xcccccc, 0xcccccc);
            c.setClipping();

            // Add a title to the chart using 15 pts Times New Roman Bold Italic font, with a light
            // grey (dddddd) background, black (000000) border, and a glass like raised effect.
            c.addTitle("Realtime Chart Demonstration", "Times New Roman Bold Italic", 15
                ).setBackground(0xdddddd, 0x000000, Chart.glassEffect());

            // Add a legend box at the top of the plot area with 9pts Arial Bold font. We set the 
            // legend box to the same width as the plot area and use grid layout (as opposed to 
            // flow or top/down layout). This distributes the 3 legend icons evenly on top of the 
            // plot area.
            LegendBox b = c.addLegend2(55, 33, 3, "Arial Bold", 9);
            b.setBackground(Chart.Transparent, Chart.Transparent);
            b.setWidth(520);

            // Configure the y-axis with a 10pts Arial Bold axis title
            c.yAxis().setTitle("Price (USD)", "Arial Bold", 10);

            // Configure the x-axis to auto-scale with at least 75 pixels between major tick and 15 
            // pixels between minor ticks. This shows more minor grid lines on the chart.
            c.xAxis().setTickDensity(75, 15);

            // Set the axes width to 2 pixels
            c.xAxis().setWidth(2);
            c.yAxis().setWidth(2);

            // Now we add the data to the chart. Access to the data buffer should be synchronized 
            // because the data buffer may be updated by another thread at real time
          //  DateTime lastTime = timeStamps[timeStamps.Length - 1];
            //if (lastTime != DateTime.MinValue)
            {
                // Set up the x-axis to show the time range in the data buffer
          //      c.xAxis().setDateScale(lastTime.AddSeconds(
            //        -dataRateTimer.Interval * timeStamps.Length / 1000), lastTime);

                // Set the x-axis label format
                c.xAxis().setLabelFormat("{value}");

                // Create a line layer to plot the lines
                LineLayer layer = c.addLineLayer2();

                // The x-coordinates are the timeStamps.
//                layer.setXData(timeStamps);
                layer.setXData(counters);

                // The 3 data series are used to draw 3 lines. Here we put the latest data
                // values as part of the data set name, so you can see them updated in the
                // legend box.
                layer.addDataSet(dataSeriesA, 0xff0000, "Software: <*bgColor=FFCCCC*>" +
                    c.formatValue(dataSeriesA[dataSeriesA.Length - 1], " {value|2} "));
                layer.addDataSet(dataSeriesB, 0x00cc00, "Hardware: <*bgColor=CCFFCC*>" +
                    c.formatValue(dataSeriesB[dataSeriesB.Length - 1], " {value|2} "));
                layer.addDataSet(dataSeriesC, 0x0000ff, "Services: <*bgColor=CCCCFF*>" +
                    c.formatValue(dataSeriesC[dataSeriesC.Length - 1], " {value|2} "));

                //
                // To show the capabilities of ChartDirector, we are add a movable threshold 
                // line to the chart and dynamically print a warning message on the chart if
                // a data value exceeds the threshold
                //

                // Add a red mark line to the chart, with the mark label shown at the left of
                // the mark line.
                double threshold = (double)alarmThreshold.Value;
                Mark m = c.yAxis().addMark(threshold, 0xff0000, "Alarm = " + threshold);
                m.setAlignment(Chart.Left);
                m.setBackground(0xffcccc);

                if ((dataSeriesC[dataSeriesC.Length - 1] > threshold) ||
                    (dataSeriesB[dataSeriesB.Length - 1] > threshold))
                {
                    // Add an alarm message as a custom text box on top-right corner of the 
                    // plot area if the latest data value exceeds threshold.
                    c.addText(575, 62, "Alarm - Latest Value Exceeded Threshold",
                        "Arial Bold Italic", 10, 0xffffff, Chart.TopRight).setBackground(0xdd0000);
                }

                // Fill the region above the threshold as semi-transparent red (80ff8888)
                c.addInterLineLayer(layer.getLine(1), m.getLine(), unchecked((int)0x80ff8888), Chart.Transparent);
                c.addInterLineLayer(layer.getLine(2), m.getLine(), unchecked((int)0x80ff8888), Chart.Transparent);
            }

            // Set the chart image to the WinChartViewer
            winChartViewer1.Image = c.makeImage();
        }

      
    }
}

  Re: Like to know how the Realtimechart
Posted by Peter Kwan on Apr-16-2010 02:19
Hi Pramilav,

Please perform the following modifications:

(a) Your are only displaying 10 samples, but your are generating 50 point per second (one point every 20 ms). So it is hard for you to see the points. For testing, please generate the data slowly, so you can see them and debug the code. (Or you can increase the number of points displayed, so you can see a lot of points easily.)

'one second per point
dataRateTimer.Interval = 1000;

(b) You have commented out the code for x-axis scale. You need to replace it with code to scale the x-axis as suitable for your data. If your x-coordinates are numbers, please use setLinearScale, like:

c.xAxis().setLinearScale(counters[counters.Length - 1] - (counters.Length - 1),
counters[counters.Length - 1]);
c.xAxis().setRounding(false, false);

Hope this can help.

Regards
Peter Kwan