2

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:

image

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.

Tatranskymedved
  • 4,194
  • 3
  • 21
  • 47
Joel
  • 5,732
  • 4
  • 37
  • 65
  • Possible duplicate of [How do I calculate a trendline for a graph?](https://stackoverflow.com/questions/43224/how-do-i-calculate-a-trendline-for-a-graph) – Cee McSharpface Jul 10 '18 at 09:40
  • @edit: a linear regression trendline is straight. do you need a nonlinear approximation? – Cee McSharpface Jul 10 '18 at 09:42
  • @dlatikay yes! thats one way you could phrase it i guess. I'm using dummy-data now since i don't have access to the machine that produces these values, hence the linear example. I also need to generate the curves from files, which in itself poses another problem for me. – Joel Jul 10 '18 at 09:44
  • [something like this](https://www.codeproject.com/Questions/224097/How-to-draw-trendline-in-graph-using-Windows-Forms)? the chart component you're using, `Forms.DataVisualization.Charting`, seems to have builtin capability to use Linear vs. Exponential trend graphs (I did not try this code, no idea if it actually works) – Cee McSharpface Jul 10 '18 at 09:56
  • [This](https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.datamanipulator(v=vs.110).aspx) may work, but afaik only on a point-by-point basis, that is, it only works if all series are aligned, i.e. have the same x-values. There is a function to insert missing datapoints, but I'm not sure a) if that helps nor b) if the data from OP are aligned or not. – TaW Jul 10 '18 at 10:17

1 Answers1

2

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:

enter image description here

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;
TaW
  • 53,122
  • 8
  • 69
  • 111
  • Thank you so much for clearing this up! In the meantime, i've been stuck with another problem and have since gotten a very strange behaviour, i posted it in a separate thread: https://stackoverflow.com/questions/51264338/c-sharp-chart-multiple-curves-gets-shown-next-to-eachother-instead-of-ontop – Joel Jul 10 '18 at 13:11
  • I have tweaked the code a little and added a correction for the stripline.offset and a few freehand notes ;-) – TaW Jul 10 '18 at 17:51