horizontal ScrollBar in MsChart - c#

Somewhere in internet I found this code
private void PopulateChart()
{
int elements = 500;
Random r = new Random();
List<double> xValues = new List<double>();
double currentX = 0;
for (int i = 0; i < elements; i++)
{
xValues.Add(currentX);
currentX = currentX + r.Next(1, 2000);
}
List<double> yValues = new List<double>();
for (int i = 0; i < elements; i++)
{
yValues.Add(r.Next(0, 50));
}
// remove all previous series
chart1.Series.Clear();
var series = chart1.Series.Add("MySeries");
series.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Stock;
//series.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Auto;
DateTime baseDate = DateTime.Today;
for (int i = 0; i < xValues.Count; i++)
{
var xDate = baseDate.AddSeconds(xValues[i]);
var yValue = yValues[i];
series.Points.AddXY(xDate, yValue);
}
// show an X label every itme interval (values in minute 60 = 1 hour)
chart1.ChartAreas[series.ChartArea].AxisX.Interval = 100.0;
chart1.ChartAreas[0].AxisX.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Minutes;
// label format
chart1.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss";
}
This displays random data in chart with grouping of data with some time interval.
Now I want to put a horizontal scrollbar (x-axis). I tried using code used in this post
Adding a scroll bar to MS Chart control C#
but I couldnot apply it with full functionality.
Can anyone help me in this problem?

You have enable the X axis for zooming.
chart1.ChartAreas["ChartArea1"].CursorX.IsUserEnabled = true;
chart1.ChartAreas["ChartArea1"].CursorX.IsUserSelectionEnabled = true;
chart1.ChartAreas["ChartArea1"].AxisX.ScaleView.Zoomable = true;
chart1.ChartAreas["ChartArea1"].AxisX.ScrollBar.IsPositionedInside = true;

Related

Real time ecg data in WinForms Chart c# problem

I am trying to display real time ecg data output from a device to a Winforms chart.
It's working pretty well, but I can't seem to remove the data points from the left hand side of the chart as new points are added, and the major grids shrink and grow.
Here is the code in the timer:
private void butPlayEKG_Click(object sender, EventArgs e) {
chartEKG.Series.Clear();
var series1 = new Series {
Name = "EKG",
Color = Color.LawnGreen,
IsVisibleInLegend = true,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line,
};
this.chartEKG.Series.Add(series1);
playButtonClicked = true;
timer1.Enabled = true;
timer1.Interval = 5;
timer1.Tick += (s, args) => timer1_Tick(series1);
timer1.Start();
}
private void timer1_Tick(Series series1) {
labelClock.Text = DateTime.Now.ToString("HH:mm:ss tt");
string str = String.Empty;
for (int j = 0; j < ekgData.Count; j++) {
str = ekgData[j].EKGWaveform.ToString();
count = str.Split('^');
EKGData = new int[count.Length];
string timeStamp = ekgData[j].VSTimeStamp.ToString();
string format = "yyyyMMddHHmmssfff";
DateTime time = DateTime.ParseExact(timeStamp, format, null);// CultureInfo.InvariantCulture);
adjTime = time;
if (j > 0) {
adjTime = time; time.AddSeconds(1 / 500);
}
for (int i = 0; i < 499; i++) {
EKGData = Array.ConvertAll<string, int>(count, Convert.ToInt32);
series1.Points.AddXY(adjTime.ToString("HH:mm:ss tt"), EKGData[i] * .61);
chartEKG.Update();
}
for (int h = 1; h < j; h++) {
series1.Points.Remove(series1.Points[h]);
chartEKG.Update();
}
}
}
and here is the chart code:
timer1.Interval = 15;
this.chartEKG.ChartAreas["ChartArea1"].CursorX.LineColor = Color.LawnGreen;
this.chartEKG.ChartAreas["ChartArea1"].CursorY.LineColor = Color.LawnGreen;
this.chartEKG.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = true;
this.chartEKG.ChartAreas["ChartArea1"].AxisY.MajorGrid.Interval = 200;
this.chartEKG.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = true;
this.chartEKG.ChartAreas["ChartArea1"].AxisX.MajorGrid.Interval = 200;
this.chartEKG.ChartAreas["ChartArea1"].AxisY.Title = "mV";
this.chartEKG.ChartAreas["ChartArea1"].AxisX.Minimum = 0;
CultureInfo culture = new CultureInfo("en-US");
ekgData = AnesthVSDatas.CreateEKGWaveformObjects(8237);
A video of the playback can be viewed here:
Real time ecg data
Pay attention, time.AddSeconds(1 / 500); has no effect.
I guess you insert every time the same time in the chart.
Maybe your intent was
time = time.AddSeconds(1d / 500);
Note also the d. Because 1/500 is equal to 0.
Working now.
I realized I did not need the timer, and I needed a points.RemoveAt to remove points from the chart as more points are plotted. I also simplified things by Joining all of the messages together into one long string instead of parsing each message individually.
Here is the working code:
private System.Windows.Forms.DataVisualization.Charting.Chart chartEKG;
private System.Windows.Forms.DataVisualization.Charting.Series series1;
private List<AnesthVSData> ekgData;
private static string str;
private string[] count;
chartEKG.Series.Clear();
var series1 = new Series {
Name = "EKG",
Color = Color.LawnGreen,
IsVisibleInLegend = true,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line,
};
this.chartEKG.Series.Add(series1);
playButtonClicked = true;
labelClock.Text = DateTime.Now.ToString("HH:mm:ss tt");
string timeStamp = DateTime.Now.ToString();
for (int j = 0; j < ekgData.Count; j++) {
str = str + "^" + string.Join("^", ekgData[j].EKGWaveform.ToString());
if (j == 0) {
timeStamp = ekgData[j].VSTimeStamp; //get first VSTimeStamp in series
}
}
str = str.Remove(0, 1); //remove leading ^
count = str.Split('^');
string format = "yyyyMMddHHmmssfff";
DateTime time = DateTime.ParseExact(timeStamp, format, CultureInfo.InvariantCulture);
//adjTime = time;
for (int j = 0; j < count.Length; j++) {
time = time.AddSeconds(0.002); //500 data points per HL7 message, each message is 1s long so 1/500 = 0.002
series1.Points.AddXY(time.ToString("HH:mm:ss"), Convert.ToInt32(count[j]) * 0.61); // 0.61 is resolution correction factor
if (chartEKG.Series[0].Points.Count > 1800) {
chartEKG.Series[0].Points.RemoveAt(0);
chartEKG.ChartAreas[0].AxisX.Minimum = 0; }
chartEKG.Update();
}
And here is the output:
ekg waveform demo

Average of of 2 coordinates

So I am making a graph of the average between to lists of coordinates.
So I have been looking all over and can't seem to find any information on how I can find the average of the 2 lists of values. When I try I get an error "the index was outside the matrix boundaries" and when I got it to work I just made a graph where the years where extremely high and the graph itself were looking insane. What i do is importing 2 parts of(data/data2) information with Json.
//
// Data
//
int tal = dataSet.dataset.value.Count;
//Add items in the listview
int[] yData = new int[tal];
int[] xData = new int[tal];
int k = 0;
foreach (var item in dataSet.dataset.dimension.Tid.category.label)
{
xData[k++] = int.Parse(item.Value.ToString());
}
for (int i = 0; i < tal; i++)
{
yData[i] = dataSet.dataset.value[i];
}
//
// Data2
//
int tal2 = dataSet2.dataset.value.Count;
int[] y2Data = new int[tal2];
int[] x2Data = new int[tal2];
int j = 0;
foreach (var item in
dataSet2.dataset.dimension.Tid.category.label)
{
x2Data[j++] = int.Parse(item.Value.ToString());
}
for (int p = 0; p < tal2; p++)
{
y2Data[p] = dataSet2.dataset.value[p];
}
This is the part
///////////////////////////////////////////////////////////
int[] ySum = new int[xData.Length];
for (int i = 0; i < xData.Length; i++)
{
ySum[i] = (yData[i] + y2Data[i]) / 2;
}
///////////////////////////////////////////////////////////
List<int> GenUd = new List<int>(yData.ToList());
textBoxGenUd.Text = GenUd.Average().ToString();
List<int> GenInd = new List<int>(y2Data.ToList());
textBoxGenInd.Text = GenInd.Average().ToString();
chartArea1.Name = "ChartArea1";
chart2.ChartAreas.Add(chartArea1);
chart2.Dock = DockStyle.Fill;
for (int i = 0; i <xData.Count(); i++)
{
series1.Points.AddXY(ySum[i], x2Data[i]);
}
MySecChart2 mc3 = new MySecChart2(series1);
mc3.ShowDialog();
mine is just an educated guess - if the exception occurs at the following:
This is the part
///////////////////////////////////////////////////////////
int[] ySum = new int[xData.Length];
for (int i = 0; i < xData.Length; i++)
{
ySum[i] = (yData[i] + y2Data[i]) / 2;
}
///////////////////////////////////////////////////////////
My diagnosis would be that yData[i] and y2Data[i] they dont have the same length and of xData.Length define into the loop definition.
Was perhaps supposed to be yData.Length in the loop definition?

Graph with uneven intervals on y axis

I've tried without luck do make such graph in WinForms with Chart control.Graph with uneven intervals on y axis My first idea was to use pointed Chart with images for empty and not empty marker. The lines are displayed, but unfortunatelly there is a big space between values 4 - 19 and 20 - 33. Is there a way to avoid the space when using standard WinForms chart Control?
My second idea was to use a DatagridView. I could add not more that something aboit 700 columns. I would need almost 2000 columns. Thus the DataGridView isn't best choice for me.
Thank for any hint how to achieve it.
Edit 1:
As sugested by TnTinMn I've tried ScaleBreakStyle. This seems to remove some spaces from the graph. At the moment my graph looks like this:
This was achieved by the Code:
var chartArea = chart1.ChartAreas[series.ChartArea];
chartArea.AxisX.LabelStyle.IsStaggered = false;
chartArea.AxisX.Minimum = 0;
chartArea.AxisX.Maximum = (int)numericUpDown1.Value;
chartArea.AxisX.IsReversed = true;
chartArea.AxisX.Interval = 1;
chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Number;
chartArea.AxisY.ScaleBreakStyle.Enabled = true;
chartArea.AxisY.ScaleBreakStyle.BreakLineStyle = BreakLineStyle.None;
chartArea.AxisY.ScaleBreakStyle.Spacing = 0;
chartArea.AxisY.ScaleBreakStyle.CollapsibleSpaceThreshold = 50;
chartArea.AxisY.Interval = 1;
If I try to put the y labels on the left side, it doesn't work
chartArea.AxisY.Enabled = AxisEnabled.False;
chartArea.AxisY2.Enabled = AxisEnabled.True;
Adding folowing code doesn't solve the problem:
chartArea.AxisY2.ScaleBreakStyle.Enabled = true;
chartArea.AxisY2.ScaleBreakStyle.BreakLineStyle = BreakLineStyle.None;
chartArea.AxisY2.ScaleBreakStyle.Spacing = 0;
chartArea.AxisY2.ScaleBreakStyle.CollapsibleSpaceThreshold = 50;
chartArea.AxisY2.Interval = 1;
How can I remove 26 and 28, and leave only 1 and 27 on the chart? How can I put 1 and 27 on the bottom and leave a "big" space above them?
Edit 2:
After some tryies I've achieved what I wanted(I still have to adjust the marker images, but it looks very promising).
This is what I have at the moment:
As TnTiMn said, it is a little bit tricky. I had to map 1, 2, 3... to my real values and then to assign custom labels. I didn't used ScaleBreakStyle. Thanks anyway for your help.
My code:
chart1.ChartAreas[0].AxisX.IsReversed = true;
chart1.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chart1.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chart1.ChartAreas[0].AxisY2.MajorGrid.Enabled = false;
chart1.ChartAreas[0].AxisY.Enabled = AxisEnabled.False;
chart1.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chart1.ChartAreas[0].AxisY2.ScaleView.SizeType = DateTimeIntervalType.Number;
chart1.ChartAreas[0].AxisY2.MajorTickMark.Enabled = false;
chart1.Series[0].MarkerImage ="NotEmptyPoint.png";
chart1.Series[0].EmptyPointStyle.MarkerImage = "EmptyPoint.png";
chart1.Series[1].MarkerImage = "NotEmptyPoint.png";
chart1.Series[1].EmptyPointStyle.MarkerImage = "EmptyPoint.png";
chart1.Series[2].MarkerImage = "NotEmptyPoint.png";
chart1.Series[2].EmptyPointStyle.MarkerImage = "EmptyPoint.png";
chart1.ChartAreas[0].AxisY.Interval = 1;
chart1.ChartAreas[0].AxisY2.Interval = 1;
chart1.ChartAreas[0].AxisY2.Minimum = 0;
chart1.ChartAreas[0].AxisY2.Maximum = 10;
chart1.ChartAreas[0].AxisY.Minimum = 0;
chart1.ChartAreas[0].AxisY.Maximum = 10;
int number = 0;
string mappedNumber;
for (int i = 1; i < 15; i++)
{
number = 1;
mappedNumber = "1";
chart1.Series["Series1"].Points.AddXY(i, number);
chart1.ChartAreas[0].AxisY2.CustomLabels.Add(number - 0.5, number + 0.5, mappedNumber);
if(i % 3 == 0)
{
chart1.Series["Series1"].Points[chart1.Series["Series1"].Points.Count - 1].IsEmpty = true;
}
}
for (int i = 1; i < 15; i++)
{
number = 2;
mappedNumber = "7";
chart1.Series["Series2"].Points.AddXY(i, number);
chart1.ChartAreas[0].AxisY2.CustomLabels.Add(number - 0.5, number + 0.5, mappedNumber);
if (i % 4 == 0)
{
chart1.Series["Series2"].Points[chart1.Series["Series2"].Points.Count - 1].IsEmpty = true;
}
}
for (int i = 1; i < 15; i++)
{
number = 3;
mappedNumber = "20";
chart1.Series["Series3"].Points.AddXY(i, number);
chart1.ChartAreas[0].AxisY2.CustomLabels.Add(number - 0.5, number + 0.5, mappedNumber);
if (i % 5 == 0)
{
chart1.Series["Series3"].Points[chart1.Series["Series3"].Points.Count - 1].IsEmpty = true;
}
}

How to edit a asp.net chart X Axis label and only show date and not time

How do I remove the time from the X Axis in my chart.
My sql returns date only but my code adds the time again.
I have tried:
Chart1.ChartAreas[0].AxisX.LabelStyle.Format = "##-##-##";
But no luck.
My current code:
Chart1.Visible = ddlChart.SelectedValue != "";
string query = string.Format(stest);
DataTable dt = GetData(query);
string[] x = new string[dt.Rows.Count];
int[] y = new int[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
x[i] = dt.Rows[i][0].ToString();
y[i] = Convert.ToInt32(dt.Rows[i][1]);
}
Chart1.Series[0].Points.DataBindXY(x, y);
Chart1.Series[0].ChartType = SeriesChartType.Bar;
Chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true;
Chart1.Legends[0].Enabled = true;
WORKING CODE - Thanks jstreet
Chart1.Visible = ddlChart.SelectedValue != "";
string query = string.Format(stest);
DataTable dt = GetData(query);
DateTime[] x = new DateTime [dt.Rows.Count];
int[] y = new int[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
x[i] = Convert.ToDateTime(dt.Rows[i][0]);
y[i] = Convert.ToInt32(dt.Rows[i][1]);
}
Chart1.Series[0].Points.DataBindXY(x, y);
Chart1.ChartAreas[0].AxisX.LabelStyle.Format = "MM-dd-yyyy";
Chart1.Series[0].ChartType = SeriesChartType.Bar;
Chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true;
Chart1.Legends[0].Enabled = true;
In a Bar chart (as opposed to a Column chart), the vertical axis is the AxisX, not AxisY. Also, avoid assigning a string to your AxisX. It is not necessary at all and may cause problems.
Use this:
Chart1.ChartAreas[0].AxisX.LabelStyle.Format = "MM-dd-yyyy";
or this:
Chart1.ChartAreas[0].AxisX.LabelStyle.Format = "MM-dd-yy";
EDIT:
Here's some sample code:
protected void Page_Load(object sender, EventArgs e)
{
DateTime[] x = new DateTime[3];
int[] y = new int[3];
for (int i = 0; i < 3; i++)
{
x[i] = DateTime.Now.AddDays(i);
y[i] = 10 * (i + 1);
}
Chart1.Series[0].Points.DataBindXY(x, y);
Chart1.ChartAreas[0].AxisX.LabelStyle.Format = "MM-dd-yy";
}
The following below should work
for (int i=0; i < dt.Rows.Count; i++)
{
DataRow row = dt.Rows[i];
x[i] = DateTime.ParseExact(row[0].ToString(), 'MM-dd-yy', CultureInfo.InvariantCulture);
y[i] = Convert.ToInt32(row[1]);
}

How to draw vertical lines representing dicrete graph with ZedGraph library in C#?

Here's the code I use to draw the discrete graph:
private void DrawHartleyGraph(double [] values, ZedGraphControl zed)
{
GraphPane pane = zed.GraphPane;
pane.CurveList.Clear();
pane.XAxis.Title.Text = "ν";
pane.YAxis.Title.Text = "H(ν)";
pane.Title.Text = "ДПХ";
PointPairList list = new PointPairList();
for (int i = 0; i < values.Length ; i++)
{
list.Add((double)i, values[i]);
}
LineItem myCurve = pane.AddCurve("H(ν) - ДПХ", list, Color.Blue, SymbolType.Circle);
myCurve.Line.IsVisible = false;
myCurve.Symbol.Fill.Color = Color.Blue;
myCurve.Symbol.Fill.Type = FillType.Solid;
myCurve.Symbol.Size = 4;
pane.XAxis.Scale.Min = 0;
pane.XAxis.Scale.Max = numOfCountsN;
pane.YAxis.Scale.Min = values.Min();
pane.YAxis.Scale.Max = values.Max();
pane.IsBoundedRanges = true;
zed.AxisChange();
zed.Invalidate();
}
I've got the picture like this:
How can I draw vertical lines beginning on the X-Axis and ending in the point, representing the value of function?
Solved
Here is the found decision. You need to modify the for-cycle this way:
for (int i = 0; i < values.Length ; i++)
{
list.Add((double)i, values[i]);
LineObj vertLine = new LineObj(Color.Red, i, 0,
i, values[i]);
pane.GraphObjList.Add(vertLine);
}

Categories