Chart control data series - c#

I have a chart control.I am plotting price along y axis and month-year along x axis.
I add series1 1st and then series2 to the same chart area.
Then I plot the points for series 1 and 2 using the below code
curveChart.Series.Add("Series1");
curveChart.Series["Series1"].XValueType = ChartValueType.DateTime;
curveChart.Series["Series1"].Points.DataBind(list1, "MonthYear", "PriceValue", null);
curveChart.Series["Series1"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
curveChart.Series["Series1"].BorderWidth = 3;
curveChart.ChartAreas["0"].AxisX.Interval = 1;
curveChart.Series.Add("Series2");
curveChart.Series["Series2"].XValueType = ChartValueType.DateTime;
curveChart.Series["Series2"].Points.DataBind(list2, "MonthYear", "PriceValue", null);
curveChart.Series["Series2"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
curveChart.Series["Series2"].BorderWidth = 3;
curveChart.ChartAreas["0"].AxisX.Interval = 1;
The problem I am facing is that list2 contains data only till Dec-2015 and list1 contains data till Dec-2016 but when the graph is plotted both the lines in the graph extend upto Dec-2016 though list2 doesnt have data till Dec-2016.How can I solve this?

I tried to simulate your problem. I added two data series one with 3 points, one with 2 points. The chart rendered correctly. This makes me think you are going to have to massage your data before you bind it.
curveChart.Series.Clear();
curveChart.Series.Add("Series1");
curveChart.Series["Series1"].XValueType = ChartValueType.DateTime;
curveChart.Series["Series1"].Points.AddXY(DateTime.Now, 12.00m);
curveChart.Series["Series1"].Points.AddXY(DateTime.Now.AddDays(1), 13m);
curveChart.Series["Series1"].Points.AddXY(DateTime.Now.AddDays(2), 8m);
curveChart.Series["Series1"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
curveChart.Series["Series1"].BorderWidth = 3;
curveChart.ChartAreas["0"].AxisX.Interval = 1;
curveChart.Series.Add("Series2");
curveChart.Series["Series2"].XValueType = ChartValueType.DateTime;
curveChart.Series["Series2"].Points.AddXY(DateTime.Now, 5.00m);
curveChart.Series["Series2"].Points.AddXY(DateTime.Now.AddDays(1), 7m);
curveChart.Series["Series2"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
curveChart.Series["Series2"].BorderWidth = 3;
curveChart.ChartAreas["0"].AxisX.Interval = 1;

Related

RangeColumn: Show difference between two y values as Label

I have a RangeColumn with two y values per DataPoint. In the chart I would like to see the datapoint labeled with the difference of the two y values.
I tried:
DataPoint p = new DataPoint();
p.SetValueXY(d.Date, prev, prev + biggerResult.Count);
p.Label = biggerResult.Count.ToString();
s_AC_Checked.Points.AddXY(d.Date, prev, prev+biggerResult.Count);
Also this is not bringing me further:
s_AC_Checked.Label = "#VALY1\n#VALY2\n#VALY2-#VAL1\n#LABEL";
No chance to see the difference between the y values.
Here is what appears:
The right column should show "5" as a difference ...
Picture:
https://i.stack.imgur.com/r7Ejn.png
Found it. Doing it after the point was added to the series does the trick ...
DataPoint p = new DataPoint();
p.SetValueXY(d.Date, prev, prev + biggerResult.Count);
int index = s_AC_Checked.Points.AddXY(d.Date, prev, prev+biggerResult.Count);
DataPoint pt = s_AC_Checked.Points[index];
pt.Label = biggerResult.Count.ToString();
pt.SetCustomProperty("LabelStyle", "Left");
pt.LabelForeColor = Color.Black;
pt.IsValueShownAsLabel = true;

generate a trendline from files in a chart

I want to be able to fetch .csv files from a folder and plot them up in a chart.
Currently, I'm just saving the files and displaying an individual curve like this:
RunTest function:
public List<Tuple<double,double>> runTest()
{
_dpg = new Root(this, "english", false);
_dpg.Init();
var filename = "Dpg10Export_" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".csv";
List<Tuple<double, double>> results = new List<Tuple<double, double>>();
var measurement = new Measurement();
var resultCode = RunMeasurement(60, 1000, 2200, ref measurement, null /* TODO: ref ProgressBar? */);
using (var fileStream = new StreamWriter(filename))
{
var count = measurement.I_inc_Values.Count;
for (var i = 0; i < count; i++)
{
var item = measurement.I_inc_Values[i + 1];
var current = (float)Convert.ToDouble(item);
item = measurement.LI_inc_Values[i + 1];
var inductance = (float)Convert.ToDouble(item);
var line = current.ToString() + ";" + inductance.ToString() + ";";
fileStream.WriteLine(line);
currentList.Add(current);
inductanceList.Add(inductance);
results.Add(new Tuple<double, double>(current,inductance));
if (i == 0 || (i + 1) % 32 == 0)
{
Console.WriteLine((i + 1) + ": " + line);
}
}
}
return results;
}
This code produces a csv-file that looks something like this:
0,22 | 0,44
0,32 | 0,54
0,44 | 0,65
And those values produce a curve that looks like this:
When you click on the "get Waveform" button, the curve above is generated. However, I want to display all the curves that has been generated, and a trendline as well. How would I achieve this?
void BindData(List<Tuple<double,double>> results)
{
chart.Series.Clear();
var series1 = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "curr/induc",
Color = System.Drawing.Color.Green,
IsVisibleInLegend = true,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line
};
foreach (var i in results)
{
series1.Points.AddXY(i.Item2,i.Item1);
}
chart.Invalidate();
chart.Series.Add(series1);
}
private void getWaveformBtn_Click(object sender, EventArgs e)
{
Dpg10Client.Dpg10Settings settings = new Dpg10Client.Dpg10Settings();
Dpg10Instrument hej = new Dpg10Instrument(settings);
List<Tuple<double,double>> results = hej.runTest();
double current, inductance;
foreach(var i in results)
{
current = i.Item1;
inductance = i.Item2;
textBoxWaveformInput.Text += current.ToString() + inductance.ToString();
}
BindData(results);
}
TL;DR
Parse the information from the CSV files to generate curves, and create a trendline based on those files.
Marked as duplicate: That answer is regarding a straight line, these values can fluctuate in a curve.
There are many ways to solve most of the various problems in your question.
Let me tackle only the one that actually has to do with calculating an average from multiple series, i.e. will not deal with creating a Series with data from a CSV file.
There is a built-in class that can do all sorts of advanced math, both financial and statistical, but I didn't find one that will help in creating an average line/curve over more than one series.
So let's do it ourselves..
The first issue is that to calculate averages we need not just data but the data, that is their x-values, must be grouped into 'bins' from which we want to get the averages.
Unless the data already are grouped like that, e.g. because they have one value per series per day, we need to create such groups.
Let's first collect all the points from all series we want to handle; you may need to adapt the loop to include just your set of series..:
var allPoints = new List <DataPoint>();
for (int s = 0; s < 3; s++) // I know I have created these three series
{
Series ser = chartGraphic.Series["S" + (s+1)];
allPoints.AddRange(ser.Points);
}
Next we need to decide on a bin range/size, that is a value that determines which x-values shall fall into the same bin/group. I chose to have 10 bins.
So we best get the total range of the x-values and divide by the number of bins we want..:
double xmax = allPoints.Max(x => x.XValue);
double xmin = allPoints.Min(x => x.XValue);
int bins = 10;
double groupSize = (xmax - xmin) / (bins - 1);
Next we do the actual math; for this we order our points, group them and select the average for each grouped set..:
var grouped = allPoints
.OrderBy(x => x.XValue)
.GroupBy(x => groupSize * (int)(x.XValue /groupSize ))
.Select(x => new { xval = x.Key, yavg = x.Average(y => y.YValues[0]) })
.ToList();
Now we can add them to a new series to display the averages in the bins:
foreach (var kv in grouped) avgSeries.Points.AddXY(kv.xval + groupSize/2f, kv.yavg);
I center the average point in the bins.
Here is an example:
A few notes on the example:
The average line doesn't show a real 'trend' because my data are pretty much random.
I have added Markers to all series to make the DataPoints stand out from the lines. Here it is how I did it for the averages series:
avgSeries.MarkerStyle = MarkerStyle.Cross;
avgSeries.MarkerSize = 7;
avgSeries.BorderWidth = 2;
I have added a StripLine to show the bins. Here is how:
StripLine sl = new StripLine();
sl.BackColor = Color.FromArgb(44,155,155,222);
sl.StripWidth = groupSize;
sl.Interval = groupSize * 2;
sl.IntervalOffset = chartGraphic.ChartAreas[0].AxisX.IntervalOffset;
chartGraphic.ChartAreas[0].AxisX.StripLines.Add(sl);
I have also set one point to have a really low value of -300 to demonstrate how this will pull down the average in its bin. To keep the chart still nicely centered on the normal range of data I have added a ScaleBreakStyle to the y-axis:
chartGraphic.ChartAreas[0].AxisY.ScaleBreakStyle.BreakLineStyle = BreakLineStyle.Wave;
chartGraphic.ChartAreas[0].AxisY.ScaleBreakStyle.Enabled = true;

C# simply chart binding

The idea is to simply to plot arrD[i] in a chart called chart5 SeriesA. The issue is that nothing is plotted in the windows form. Maybe someone could help. Many thanks.
chart5 = new Chart();
Series SeriesA = new Series();
Dictionary<int, double> value5 = new Dictionary<int, double>();
for (int i = 0; i < monthCount; i++)
{
value5.Add(i, arrD[i]);
}
SeriesA.XValueMember = "Location";
SeriesA.YValueMembers = "Value";
chart5.DataSource = value5;
chart5.Series.Add("SeriesA");
You do not add the series you created to your chart.
Try this code :
Series SeriesA = new Series();
SeriesA.Points.DataBind(arrD, "Location", "Value", "");
chart5.Series.Add(SeriesA);
Note that we add SeriesA and not "SeriesA"
Ok, I simplified the binding (which works well now) as well as the loop for hiding the zero values. But how to print now the modified chart without zero values .. many thanks.
chart7.Series["Series3"].ChartType = SeriesChartType.Line;
chart7.Series["Series3"].Points.DataBindXY(xVal, arrDouble3);
foreach (Series series in chart7.Series)
{
foreach (DataPoint arrP in series.Points)
{
if (arrP.YValues.Length > 0 && (double)arrP.YValues.GetValue(0) == 0)
{
arrP.IsValueShownAsLabel = false;
}
}
}
chart7.Series["Series3"].Points.DataBindXY(xVal, arrP); ????

Adding series to Excel chart exception

I have an excel file filled with some data. I am trying to open the second sheet and create a chart. The problem is that the Series are giving me either a System.Runtime.InteropServices.COMException was caught or if I un-comment the commented lines a No overload for method 'SeriesCollection' takes '0' arguments. Here is the code that I have:
Microsoft.Office.Interop.Excel.ChartObjects chartObjs = (Microsoft.Office.Interop.Excel.ChartObjects)ws.ChartObjects(Type.Missing);
Microsoft.Office.Interop.Excel.ChartObject chartObj = chartObjs.Add(100, 20, 300, 300);
Microsoft.Office.Interop.Excel.Chart xlChart = chartObj.Chart;
Range rg1 = ws.get_Range("A1", "D" + rowcount);
rg1.VerticalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
xlChart.SetSourceData(rg1, Microsoft.Office.Interop.Excel.XlRowCol.xlColumns);
xlChart.ChartType = XlChartType.xlLine;
xlChart.Legend.Position = XlLegendPosition.xlLegendPositionBottom;
Axis axis = (Axis)xlChart.Axes(Microsoft.Office.Interop.Excel.XlAxisType.xlValue, Microsoft.Office.Interop.Excel.XlAxisGroup.xlPrimary);
axis.MaximumScaleIsAuto = false;
axis.MaximumScale = 3;
Axis Xaxis = (Axis)xlChart.Axes(Microsoft.Office.Interop.Excel.XlAxisType.xlCategory, Microsoft.Office.Interop.Excel.XlAxisGroup.xlPrimary);
Xaxis.TickLabels.Orientation = XlTickLabelOrientation.xlTickLabelOrientationDownward;
//SeriesCollection seriesCollection = (SeriesCollection)xlChart.SeriesCollection();
Series s1 = (Series)xlChart.SeriesCollection(1);
s1.Name = "Serie1";
s1.MarkerStyle = XlMarkerStyle.xlMarkerStyleCircle;
//seriesCollection.NewSeries();
Series s2 = (Series)xlChart.SeriesCollection(2);
s2.Name = "Serie2";
s2.MarkerStyle = XlMarkerStyle.xlMarkerStyleNone;
//seriesCollection.NewSeries();
Series s3 = (Series)xlChart.SeriesCollection(3);
s3.Name = "Serie3";
s3.MarkerStyle = XlMarkerStyle.xlMarkerStyleNone;
If I keep the comments, the error says invalid parameter and is shown on that line:
Series s2 = (Series)xlChart.SeriesCollection(2);
If I remove the comments, I get the second exception on that line:
SeriesCollection seriesCollection = (SeriesCollection)xlChart.SeriesCollection();
If I add 1 as a parameter, then the chart is not displayed properly. Do you have any suggestions how to make it work?
Argh that stuff still gives me nightmares. There was some weirdness around SeriesCollection - but I cannot remember exactly what it was.
Try to re-include that line
//SeriesCollection seriesCollection = (SeriesCollection)xlChart.SeriesCollection();
and refernece the seriesCollection object everywhere.
Alos it could be, that the index for SeriesCollection is zero - based, can you try that?
By Default when you create a new chart it doesn't have any series so you can't select it using chartPage.SeriesCollection(1). You need to create a series first.
In order to add a new series you need to use something like:
SeriesCollection seriesCollection = (SeriesCollection)xlChart.SeriesCollection();
Series s1 = seriesCollection.NewSeries();
s1.Name = "Serie1";
s1.MarkerStyle = XlMarkerStyle.xlMarkerStyleCircle;
Series s2 = seriesCollection.NewSeries();
s2.Name = "Serie2";
s2.MarkerStyle = XlMarkerStyle.xlMarkerStyleNone;
You may also need to add the values to the series rather than to the chart, eg:
Series ser = sc.NewSeries();
ser.XValues = _excelWorksheet.Range[YourRange];
ser.Values = _excelWorksheet.Range[YourRange];

Getting Values of other Series through tooltip

I'm having a Chart whose data is coming from a list.
This class has id and count1 and count2 as Properties...
Now, i have a list of class...where the values are...
Id Count1 Count2
1 -10 20
2 -15 15
Now,
i do a simple bind...with multiple series
Chart1.DataSource = ListObjOfThatClass
Chart1.Series[0].XValueMember = "Id";
Chart1.Series[0].YValueMembers = "Count1";
Chart1.Series[1].YValueMembers = "Count2";
Chart1.DataBind();
Now, everthing works fine..
My Que: When i hover over the DataSeries, i show a tooltip for that particular YValueMember as "#VALY";
Chart1.Series[0].ToolTip = "#VALY";
Is there any way that I can show the value present in the other series?
i.e
Count2 value, of the series[1].YValueMember which I initialized earlier...??
Thanks
The easier way is too create your own DataPoint for the series, and not use the datasource. Then you can put whatever you want in the tooltip:
foreach (var o in ListObjOfThatClass)
{
var p1 = new DataPoint();
p1.SetValueXY(o.Id, o.Count1);
p1.ToolTip = string.Format("{0}", o.Count2);
Chart1.Series[0].Points.Add(p1);
var p2 = new DataPoint();
p2.SetValueXY(o.Id, o.Count2);
Chart1.Series[1].Points.Add(p2);
}

Categories