Functions and period

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
Post Reply
Seveno Developer
Newbie
Newbie
Posts: 12
Joined: Fri Sep 30, 2016 12:00 am

Functions and period

Post by Seveno Developer » Wed Jan 11, 2017 3:06 am

Hi Support,

We have an issue with the function series, we are trying to populate a Add function series on a time series data based on a daily basis for which the code as follows:

Dim funcSeries As New Steema.TeeChart.Styles.FastLine(FChart.Chart)
funcSeries.Title = String.Format("Total ({0})", periodText)
funcSeries.DataSource = _selectedSeries
funcSeries.Marks.Visible = True
Dim chartTotalFunction As New Steema.TeeChart.Functions.Add
Dim period As New TimeSpan
period = New TimeSpan(1, 0, 0, 0)
chartTotalFunction.Period = period.TotalDays
chartTotalFunction.PeriodAlign = Steema.TeeChart.Functions.PeriodAligns.Center
chartTotalFunction.PeriodStyle = Steema.TeeChart.Functions.PeriodStyles.Range
funcSeries.Function = chartTotalFunction.Period
funcSeries.CheckDataSource()

The result of function series is based on intervals of one day from starting point (24 hours from starting), but not on based on the specific date. How to get the resulting values of the function series based on each date rather than a 24 hours day?

Seveno Developer
Newbie
Newbie
Posts: 12
Joined: Fri Sep 30, 2016 12:00 am

Re: Functions and period

Post by Seveno Developer » Mon Jan 16, 2017 12:24 am

Hello..

Any input for this?

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Functions and period

Post by Christopher » Mon Jan 16, 2017 3:15 pm

Seveno Developer wrote:Hello..

Any input for this?
Sorry for the delay in this reply.

It seems there may be some defects in this area of code - I am looking at this now and will get back to you.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Functions and period

Post by Christopher » Tue Jan 17, 2017 11:27 am

Hello,

Unfortunately there were two defects in this area of code which have now been fixed and will be available in the next maintenance release. However, these fixes can be used now in a custom Add function class like this:

Code: Select all

  public class MyAdd : Add
  {
    public override double Calculate(Series source, int first, int last)
    {
      if (first == -1)
      {
        first = 0;
        last = source.Count - 1;
      }

      List<double> tmpValues = new List<double>();
      ValueList tmpSource = ValueList(source);

      for (int i = first; i <= last; i++)
      {
        if (IncludeNulls || (!source.IsNull(i)))
        {
          AddValues(tmpValues, tmpSource[i]);
        }
      }

      return CalculateValue(tmpValues.ToArray());
    }

    protected override void DoCalculation(Series source, ValueList notMandatorySource)
    {
      if (dPeriod == 0)
        CalculateAllPoints(source, notMandatorySource);
      else
        CalculateByPeriodFix(source, notMandatorySource);
    }

    private bool HasRegularStep(ValueList list)
    {
      double step, laststep = 0;

      for (int i = 1; i < list.Count; i++)
      {
        step = list[i] - list[i - 1];

        if (i > 1 && Utils.SignificantDifference(laststep, step))
        {
          return false;
        }

        laststep = step;
      }

      return true;
    }

    private void CalculateByPeriodFix(Series source, ValueList notMandatorySource)
    {
      double tmpX;
      int tmpLast;
      double PosFirst;
      double PosLast;
      bool tmpCalc;

      int tmpFirst = 0;
      int tmpCount = source.Count;
      double tmpBreakPeriod = notMandatorySource[tmpFirst];
      DateTimeSteps tmpStep = Axis.FindDateTimeStep(dPeriod);
      double actualStep = HasRegularStep(notMandatorySource) ? notMandatorySource[tmpFirst + 1] - tmpBreakPeriod : dPeriod * 0.001;

      do
      {
        PosLast = 0;
        if (PeriodStyle == PeriodStyles.NumPoints)
        {
          tmpLast = tmpFirst + Utils.Round(dPeriod) - 1;
          PosFirst = notMandatorySource[tmpFirst];
          if (tmpLast < tmpCount) PosLast = notMandatorySource[tmpLast];
        }
        else
        {
          tmpLast = tmpFirst;
          PosFirst = tmpBreakPeriod;
          Axis axis = Series.GetHorizAxis;
          Series.GetHorizAxis.DateTimeIncrement(axis.Labels.ExactDateTime && axis.IsDateTime && (tmpStep >= DateTimeSteps.HalfMonth), true, ref tmpBreakPeriod, dPeriod, tmpStep);
          PosLast = tmpBreakPeriod - (actualStep);

          while (tmpLast < tmpCount - 1)
            if (notMandatorySource[tmpLast + 1] < tmpBreakPeriod) tmpLast++;
            else
              break;
        }
        tmpCalc = false;

        if (tmpLast < tmpCount)
        {

          /* align periods */
          if (PeriodAlign == PeriodAligns.First)
            tmpX = PosFirst;
          else
            if (PeriodAlign == PeriodAligns.Last)
            tmpX = PosLast;
          else
            tmpX = (PosFirst + PosLast) * 0.5;

          if ((PeriodStyle == PeriodStyles.Range) && (notMandatorySource[tmpFirst] < tmpBreakPeriod))
            tmpCalc = true;

          if ((PeriodStyle == PeriodStyles.NumPoints) || tmpCalc)
            CalculatePeriod(source, tmpX, tmpFirst, tmpLast);
          else
            AddFunctionXY(true, tmpX, 0);
        }
        if ((PeriodStyle == PeriodStyles.NumPoints) || tmpCalc)
          tmpFirst = tmpLast + 1;
      } while (tmpFirst <= tmpCount - 1);
    }
  }
This class can be used as following:

Code: Select all

    Line series;
    FastLine funcSeries;
    MyAdd chartTotalFunction;
    private void InitializeChart()
    {
      funcSeries = new FastLine(tChart1.Chart);
      funcSeries.Marks.Visible = true;
      chartTotalFunction = new MyAdd();
      chartTotalFunction.Period = new TimeSpan(0, 12, 0, 0).TotalDays;
      chartTotalFunction.PeriodAlign = Steema.TeeChart.Functions.PeriodAligns.Last;
      chartTotalFunction.PeriodStyle = Steema.TeeChart.Functions.PeriodStyles.Range;
      funcSeries.Function = chartTotalFunction;


      series = new Line(tChart1.Chart);
      DateTime today = DateTime.Today;

      for (int i = 0; i < 20; i++)
      {
        series.Add(today, i);
        today = today.AddHours(3);
      }

      funcSeries.Marks.Visible = true;
      series.Marks.Visible = true;
      funcSeries.DataSource = series;

      tChart1.Axes.Bottom.Labels.Angle = 90;
      tChart1.Axes.Bottom.Increment = new TimeSpan(0, 3, 0, 0).TotalDays;
      tChart1.Axes.Bottom.Labels.DateTimeFormat = "dd/MM/yy hh:mm";
    }
which gives me this chart:
636202525670730716.jpg
636202525670730716.jpg (76.64 KiB) Viewed 17179 times
The above chart is now correct. Can I help you with any specific questions you may have with this?
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Seveno Developer
Newbie
Newbie
Posts: 12
Joined: Fri Sep 30, 2016 12:00 am

Re: Functions and period

Post by Seveno Developer » Fri Jan 20, 2017 2:54 am

Hi Christopher,

Thank you.

Just wondering as we need to implement the other functions too and that we allow the users to add functions at run time from the chart editor, is there any way to modify the code defects so that it reflects for all functions? We do have access to the code for the latest build.

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Functions and period

Post by Christopher » Fri Jan 20, 2017 9:50 am

Seveno Developer wrote:Just wondering as we need to implement the other functions too and that we allow the users to add functions at run time from the chart editor, is there any way to modify the code defects so that it reflects for all functions? We do have access to the code for the latest build.
Of course. The changes are in Functions/Basic.cs:
func1.PNG
func1.PNG (13.9 KiB) Viewed 17155 times
func2.PNG
func2.PNG (33.54 KiB) Viewed 17155 times
You already have the code for HasRegularStep().
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Seveno Developer
Newbie
Newbie
Posts: 12
Joined: Fri Sep 30, 2016 12:00 am

Re: Functions and period

Post by Seveno Developer » Tue Jan 24, 2017 5:42 am

Hi Christopher,

Thanks for the code, we have updated the basic.cs accordingly but the results are still incorrect.

It skips values for the first day which has only 1 row.

Screenshot for sample data
Original_series_Data_source.png
Sample data for the series
Original_series_Data_source.png (30.68 KiB) Viewed 17139 times
We are using with chart max and total functions.
Output for total function:
Total_irrelevant_value.png
total function
Total_irrelevant_value.png (31.49 KiB) Viewed 17139 times
Output for maximum function:
Maximum_irrelevant_value.png
Maximum_irrelevant_value.png (86.26 KiB) Viewed 17137 times
The results are correct when the subset of data for each day has the same number of data/ same interval (i.e date/time)

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Functions and period

Post by Christopher » Tue Jan 24, 2017 9:45 am

Seveno Developer wrote: Thanks for the code, we have updated the basic.cs accordingly but the results are still incorrect.

The results are correct when the subset of data for each day has the same number of data/ same interval (i.e date/time)
Okay - would you please be so kind as to prepare a Minimal, Complete, and Verifiable example [here] with which I can reproduce your issue here?
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Seveno Developer
Newbie
Newbie
Posts: 12
Joined: Fri Sep 30, 2016 12:00 am

Re: Functions and period

Post by Seveno Developer » Wed Jan 25, 2017 12:38 am

Hi Christopher,

We handle mostly time series data for which we need to be able to apply periodic functions. I am trying to make it simple and straight.

The forum does not allow adding text files, so I've sent the data into a .txt to your gmail address. Please use the text file to load the data for the series.

To reproduce the issue, first add a series in run time (it can be done using code too):

1. From the Chart editor, add a new series (i.e: RawDataSeries).
2. Under series Tab's General Tab, set the Horizontal Axis to Bottom and check Date Time checkbox (this is another bug as the date/time field is not recognized automatically, it throws an exception if not set manually)
3. Now under the series tab, click on Datasource, select text file
4. For the file attached here, under fields tab use Number of Header lines: 1, Separator: Tab, X: 0, Y: 1
5. Specify the file location, hit apply to populate the series

Now use the code that I have posted at the beginning. Please note the period we are using is One day and therefore the period = New TimeSpan(1, 0, 0, 0)

The total value should output individual total day's not on a 24 hours basis day. This does not work. In-fact, none of the function series' value for one day period is correct for the data given.

Hope that helps

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Functions and period

Post by Christopher » Thu Jan 26, 2017 5:26 pm

Seveno Developer wrote: The total value should output individual total day's not on a 24 hours basis day. This does not work. In-fact, none of the function series' value for one day period is correct for the data given.

Hope that helps
Thanks.

I think the issue here is that you are expecting the function to group points by Date, whereas what they are doing is by PeriodStyles.Range, that is, the points that fall within a one day Period (in this case). Maybe the difference can be seen in this example:

Code: Select all

    private void InitializeChart()
    {
      Func<string, List<Tuple<DateTime, double>>> GetData = (file) =>
      {
        List<Tuple<DateTime, double>> result = new List<Tuple<DateTime, double>>();

        List<string> lines = File.ReadAllLines(file).ToList();
        lines.RemoveAt(0);

        foreach (var line in lines)
        {
          string[] splits = line.Split('\t');
          DateTime date = DateTime.Parse(splits[0]);
          double value = double.Parse(splits[1]);
          result.Add(new Tuple<DateTime, double>(date, value));
        }

        return result;
      };

      List<Tuple<DateTime, double>> data = GetData(@"D:\FTP\data.txt");
      FastLine funcSeries = new FastLine(tChart1.Chart);
      Add chartTotalFunction = new Add();
      TimeSpan period = new TimeSpan(1, 0, 0, 0);
      chartTotalFunction.Period = period.TotalDays;
      chartTotalFunction.PeriodAlign = Steema.TeeChart.Functions.PeriodAligns.Center;
      chartTotalFunction.PeriodStyle = Steema.TeeChart.Functions.PeriodStyles.Range;
      funcSeries.Function = chartTotalFunction;

      Line series = new Line(tChart1.Chart);

      for (int i = 0; i < data.Count; i++)
      {
        DateTime date = data[i].Item1;
        double val = data[i].Item2;
        series.Add(date, val);
      }

      funcSeries.Marks.Visible = true;
      funcSeries.DataSource = series;

      tChart1.Axes.Bottom.Labels.Angle = 90;
      tChart1.Axes.Bottom.Labels.DateTimeFormat = "dd/MM/yy hh:mm";


      FastLine funcSeriesLINQ = new FastLine(tChart1.Chart);
      funcSeriesLINQ.Marks.Visible = true;
      funcSeriesLINQ.Marks.Style = MarksStyles.XY;

      var group = data.GroupBy(x => x.Item1.Date);
      foreach (var item in group)
      {
        double sum = item.Sum(x => x.Item2);

        funcSeriesLINQ.Add(item.Last().Item1, sum);  //last date of group, but could calculate center
      }
    }
which gives me this:
TChart636210480275437495.png
TChart636210480275437495.png (53.26 KiB) Viewed 17111 times
In funcSeriesLINQ we group the data by the Date, that is, by a one day (24 hour) period whereby all points are of the same day. The funcSeries, on the other hand, groups points into one day periods but not of the same day, because the first point does not start at 00:00. This is by design, although maybe not what you were expecting.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Seveno Developer
Newbie
Newbie
Posts: 12
Joined: Fri Sep 30, 2016 12:00 am

Re: Functions and period

Post by Seveno Developer » Tue Jan 31, 2017 5:35 am

In funcSeriesLINQ we group the data by the Date, that is, by a one day (24 hour) period whereby all points are of the same day. The funcSeries, on the other hand, groups points into one day periods but not of the same day, because the first point does not start at 00:00. This is by design, although maybe not what you were expecting.
Thanks Christopher, the issue is as you pointed it correctly, the first point does not start at 00:00. I have added an overloading function to the datetime increment which solves our problem.

Thanks heaps for your help. :D Cheers!

Post Reply