/// <summary>
        /// Равномерно дополняет сетку временных рядов с постоянным шагом
        /// </summary>
        public static void FillGrid(List <ITimeSeries <float> > tt)
        {
            // определяем шаг
            var s = new List <TimeSpan>();

            for (int i = 1; i < tt.Count; i++)
            {
                s.Add(tt[i].StartTime - tt[i - 1].StartTime);
            }

            s.Sort();
            var step = s[s.Count / 2];
            // длительность (в отсчетах)
            var ds = tt.ConvertAll(q => q.Data.Count);

            ds.Sort();
            var len = ds[tt.Count / 2];

            var rnd = new Random(42);

            int count = 0;

            while (count < tt.Count - 1)
            {
                // недописки
                if (tt[count + 1].Data.Count < len)
                {
                    if (tt[count + 1].StartTime - tt[count].StartTime == step)
                    {
                        var f = new float[len];
                        for (int i = 0; i < tt[count + 1].Data.Count; i++)
                        {
                            f[i] = tt[count + 1].Data[i];
                        }
                        for (int i = tt[count + 1].Data.Count; i < len; i++)
                        {
                            var ind = tt[count + 1].Data.Count - i;
                            f[i] = tt[count + 1].Data[ind < 0 ? rnd.Next(tt[count + 1].Data.Count) : ind];
                        }
                        tt[count + 1] = new TimeSeriesBase(tt[count + 1].SampleRate, tt[count + 1].StartTime, f);
                    }
                    else if (tt[count + 1].StartTime - tt[count].StartTime > step)
                    {
                        var f = new float[len];
                        // величина недописки
                        var start = len - tt[count + 1].Data.Count;

                        for (int i = 0; i < start; i++)
                        {
                            var ind = i;
                            f[i] =
                                tt[count + 1].Data[
                                    ind >= tt[count + 1].Data.Count ? rnd.Next(tt[count + 1].Data.Count) : ind];
                        }
                        for (int i = start; i < len; i++)
                        {
                            f[i] = tt[count + 1].Data[i - start];
                        }

                        tt[count + 1] = new TimeSeriesBase(tt[count + 1].SampleRate, tt[count].StartTime + step, f);
                    }
                }

                // проверка на пропуск кусков
                if (tt[count + 1].StartTime - tt[count].StartTime > step)
                {
                    // вставляем сегмент
                    // если следующий кусок есть, то

                    // определяем количество пропусков
                    int skipN =
                        (int)Math.Truncate(((tt[count + 1].StartTime - tt[count].StartTime).TotalSeconds / step.TotalSeconds - 1));

                    for (int w = 0; w < skipN; w++)
                    {
                        var f = new float[len];

                        // если слева и справа достаточно
                        if (count > skipN && skipN < tt.Count - count)
                        {
                            for (int a = 0; a < len; a++)
                            {
                                f[a] = ((skipN - w) / (float)skipN) *
                                       tt[count - w].Data[
                                    a < tt[count - w].Data.Count ? a : rnd.Next(tt[count - w].Data.Count)]
                                       +
                                       (w + 1) / (float)skipN *
                                       tt[count + 1 + skipN].Data[
                                    len - a < tt[count + 1 + skipN].Data.Count
                                               ? len - a
                                               : rnd.Next(tt[count + 1 + skipN].Data.Count)];
                            }
                        }
                        // случайный выбор кусков
                        else
                        {
                            int c1 = rnd.Next(count);
                            int c2 = rnd.Next(count, tt.Count);
                            for (int a = 0; a < len; a++)
                            {
                                f[a] = 0.5f * tt[c1].Data[
                                    a < tt[c1].Data.Count ? a : rnd.Next(tt[c1].Data.Count)]
                                       +
                                       0.5f *
                                       tt[c2].Data[
                                    len - a < tt[c2].Data.Count
                                               ? len - a
                                               : rnd.Next(tt[c2].Data.Count)];
                            }
                        }

                        tt.Insert(count + 1 + w,
                                  new TimeSeriesBase(tt[count].SampleRate,
                                                     tt[count].StartTime +
                                                     TimeSpan.FromSeconds(step.TotalSeconds * (1 + w)), f));
                    }
                }
                else
                {
                    count++;
                }
            }
        }
        public static void Fill(List <ITimeSeries <float> > tt, int skip, double gapPart)
        {
            // если начала и окончания рядов шумные,
            // можно обрезать слева-справа по некоторому количеству дискретов
            for (int i = 0; i < tt.Count - 1; i++)
            {
                if (tt[i].Data.Count > skip * 20)
                {
                    var ttt = new float[tt[i].Data.Count - skip];
                    for (int x = 0; x < ttt.Length; x++)
                    {
                        ttt[x] = tt[i].Data[x];
                    }
                    tt[i] = new TimeSeriesBase(tt[i].SampleRate, tt[i].StartTime, ttt);
                }
                if (tt[i + 1].Data.Count > skip * 20)
                {
                    var ttt = new float[tt[i + 1].Data.Count - skip];
                    for (int x = 0; x < ttt.Length; x++)
                    {
                        ttt[x] = tt[i + 1].Data[skip + x];
                    }
                    tt[i + 1] = new TimeSeriesBase(tt[i + 1].SampleRate, tt[i + 1].StartTime.AddSeconds(10), ttt);
                }
            }

            // посчитать длину ряда
            var len =
                (int)((tt[tt.Count - 1].StartTime.AddSeconds(tt[tt.Count - 1].Data.Count / tt[tt.Count - 1].SampleRate) -
                       tt[0].StartTime).TotalSeconds * tt[0].SampleRate);
            var d = new float[len];

            int cur = 0;

            for (int i = 0; i < tt.Count; i++)
            {
                for (int j = 0; j < tt[i].Data.Count; j++)
                {
                    d[cur] = tt[i].Data[j];
                    cur++;
                }
                if (cur == len)
                {
                    break;
                }
                // вычислить паузу
                var lenGap =
                    (int)
                    ((tt[i + 1].StartTime - tt[i].StartTime.AddSeconds(tt[i].Data.Count / tt[i].SampleRate)).TotalSeconds *
                     tt[i].SampleRate);

                // заполнить паузу

                // если промежуток маленький
                if (lenGap < gapPart * tt[i].Data.Count && lenGap < gapPart * tt[i + 1].Data.Count)
                {
                    for (int j = 0; j < lenGap; j++)
                    {
                        d[cur] = (float)((lenGap - j) / (double)lenGap * tt[i].Data[tt[i].Data.Count - 1 - j]
                                         + (j + 1) / (double)lenGap * tt[i + 1].Data[lenGap - 1 - j]);
                        cur++;
                    }
                }
                // иначе заполнить средним
                else
                {
                    var avg = (tt[i].Data.Average() + tt[i + 1].Data.Average()) / 2.0f;
                    for (int j = 0; j < lenGap; j++)
                    {
                        d[cur] = avg;
                        cur++;
                    }
                }
            }
            var newTs = new TimeSeriesBase(tt[0].SampleRate, tt[0].StartTime, d);

            tt.Clear();
            tt.Add(newTs);
        }