Example #1
0
        private void BuildButtonClick(object sender, RoutedEventArgs e)
        {
            //Input-------------------------------------------------------
            double[] x = GetInputForBuild(out string mistake);
            Func <double, double> func = Functions[FunctionBox.Text];

            double[] graphParams = GetGraphParams(out string graphMistake);
            //------------------------------------------------------------
            GraphErrorMessage.Text = graphMistake;
            ErrorMessage.Text      = mistake;
            if (mistake == null)
            {
                //Computing---------------------------------------------------
                double[] y = new double[x.Length];
                for (int counter = 0; counter < y.Length; counter++)
                {
                    y[counter] = func(x[counter]);
                }
                Polynom = new LagrangePolynomial(x, y);
                //------------------------------------------------------------

                //Graphics----------------------------------------------------
                PlotModel model = new PlotModel();
                model.PlotType = PlotType.XY;
                model.Series.Add(new FunctionSeries(func, graphParams[0], graphParams[1], 0.01, FunctionBox.Text));
                model.Series.Add(new FunctionSeries(Polynom.Compute, graphParams[0], graphParams[1], 0.01, "Polynom"));
                foreach (double value in x)
                {
                    OxyPlot.Annotations.PointAnnotation point = new OxyPlot.Annotations.PointAnnotation
                    {
                        X     = value,
                        Y     = func(value),
                        Shape = MarkerType.Square
                    };
                    model.Annotations.Add(point);
                }
                PlotView view = new PlotView
                {
                    Model = model
                };
                Container.Children.Add(view);
                Grid.SetColumn(view, 1);
                Grid.SetRowSpan(view, 2);
                //------------------------------------------------------------

                ComputeButton.IsEnabled = true;
            }
        }
Example #2
0
        /// <summary>
        /// Find the peaks in the current data set and adds an annotation point with the resolution to the m/z.
        /// </summary>
        private void FindPeaks()
        {
            this.mzPlotModel.Annotations.Clear();

            if (!this.ShowMz)
            {
                // This currently does not support peakfinding in bin mode due to potential headaches,
                // But as it seems users never use that mode, it is a non-issue for now.
                return;
            }

            // Create a new dictionary to work with the peak finder
            var tempFrameList = new List <KeyValuePair <double, double> >(this.uimfData.MaxBins);

            for (var i = 0; i < this.MzArray.Length && i < this.MzIntensities.Length; i++)
            {
                tempFrameList.Add(new KeyValuePair <double, double>(this.MzArray[i], this.MzIntensities[i]));
            }

            var tempList = Utilities.PeakFinder.FindPeaks(tempFrameList, 3);

            // Put the points on the graph
            foreach (var resolutionDatapoint in tempList.Peaks)
            {
                var resolutionString = resolutionDatapoint.ResolvingPower.ToString("F1", CultureInfo.InvariantCulture);

                var peakPoint = new OxyPlot.Annotations.PointAnnotation
                {
                    Text    = "R=" + resolutionString,
                    X       = resolutionDatapoint.Intensity,              // / 1.03125,
                    Y       = resolutionDatapoint.PeakCenter,
                    ToolTip = resolutionDatapoint.ToString()
                };
                this.mzPlotModel.Annotations.Add(peakPoint);
            }
        }
        /// <summary>
        /// Кластеризация K-Means
        /// </summary>
        /// <param name="plot">Модель графика OxyPlot</param>
        /// <param name="label">Label для показа информации о номере итерации</param>
        /// <param name="numberOfClusters">Число кластеров</param>
        public static void DoClusteringByKMeans(PlotView plot, Label label, int numberOfClusters)
        {
            if (plot.Model == null)
            {
                return;
            }

            //координаты точек
            List <List <double> > coordinates = new List <List <double> >();

            //заполнении информации о координатах точек
            foreach (PointAnnotation annotation in plot.Model.Annotations)
            {
                List <double> pointCoordinates = new List <double> {
                    annotation.X, annotation.Y
                };
                coordinates.Add(pointCoordinates);
            }

            Random random = new Random();

            byte[] bgrColorComponents = new byte[3];
            //цвета кластеров, выбираются случайно
            Dictionary <List <double>, OxyColor> clusterColors = new Dictionary <List <double>, OxyColor>();

            //первоначальная генерация центров кластеров
            List <List <double> > clusterCenters = AlgorithmsUtils.MakeInitialSeeds(coordinates, numberOfClusters);

            foreach (List <double> clusterCenter in clusterCenters)
            {
                foreach (PointAnnotation annotation in plot.Model.Annotations)
                {
                    // todo: разобраться со сравнением флоат-пойнт чисел
                    if (annotation.X == clusterCenter[0] && annotation.Y == clusterCenter[1])
                    {
                        random.NextBytes(bgrColorComponents);
                        //отметим на графике центры кластеров
                        UIUtils.MarkClusterCenter(annotation, OxyColor.FromRgb(bgrColorComponents[0], bgrColorComponents[1], bgrColorComponents[2]));
                        clusterColors.Add(clusterCenter, annotation.Fill);

                        #region DEBUG
                                                #if DEBUG
                        Console.WriteLine("Inital cluster center x = {0}, y = {1}", annotation.X, annotation.Y);
                                                #endif
                        #endregion
                    }
                }
            }

            bool stop = false;
            Dictionary <List <double>, List <double> > clusters = null;

            int iteration = 0;

            //цикл продолжается пока меняются координаты центров кластеров
            while (!stop)
            {
                #region DEBUG
                                #if DEBUG
                Console.WriteLine("Iteration = {0}", iteration);
                                #endif
                #endregion

                label.Content = "Iteration " + iteration;
                //отображение из координат точки в координаты центра кластера
                clusters = MakeClusters(coordinates, clusterCenters);
                foreach (KeyValuePair <List <double>, List <double> > pair in clusters)
                {
                    foreach (PointAnnotation annotation in plot.Model.Annotations)
                    {
                        // todo: разобраться со сравнением флоат-пойнт чисел
                        if (annotation.X == pair.Key[0] && annotation.Y == pair.Key[1])
                        {
                            //закрашиваем точку цветом кластера
                            annotation.Fill    = clusterColors[pair.Value];
                            annotation.ToolTip = "Cluster " + ListUtils.GetElementIndex(clusterCenters, pair.Value);
                        }
                    }
                }

                List <List <double> > oldClusterCenters = clusterCenters;
                //пересчёт центров кластеров
                clusterCenters = RecalculateCoordinateOfClusterCenters(clusters, clusterCenters);

                //если координаты центров кластеров не изменились, выходим из цикла
                if (ListUtils.IsListEqualsToAnother(clusterCenters, oldClusterCenters))
                {
                    stop = true;
                }
                //если координаты центров кластеров поменялись изменились, пересчитываем кластеры
                else
                {
                    List <OxyColor> colorValues = clusterColors.Values.ToList();
                    clusterColors.Clear();
                    for (int i = 0; i < clusterCenters.Count; i++)
                    {
                        clusterColors.Add(clusterCenters[i], colorValues[i]);
                    }

                    //удаление отображения всех центров кластеров
                    foreach (PointAnnotation annotation in plot.Model.Annotations)
                    {
                        annotation.Shape = MarkerType.Circle;
                        annotation.Size  = 4;
                    }

                    //проверка на потенциально не существующие центры кластеров
                    foreach (List <double> oldClusterCenter in oldClusterCenters)
                    {
                        bool isClusterCenterDataPoint = false;
                        foreach (List <double> coordinate in coordinates)
                        {
                            // todo: разобраться со сравнением флоат-пойнт чисел
                            if (oldClusterCenter[0] == coordinate[0] && oldClusterCenter[1] == coordinate[1])
                            {
                                #region DEBUG
                                                                #if DEBUG
                                Console.WriteLine("ex-center x = {0}, y = {1}", oldClusterCenter[0], oldClusterCenter[1]);
                                                                #endif
                                #endregion

                                isClusterCenterDataPoint = true;
                                break;
                            }
                        }
                        //если центр кластера не является точкой данных
                        if (!isClusterCenterDataPoint)
                        {
                            foreach (PointAnnotation annotation in plot.Model.Annotations)
                            {
                                // todo: разобраться со сравнением флоат-пойнт чисел
                                if (annotation.X == oldClusterCenter[0] && annotation.Y == oldClusterCenter[1])
                                {
                                    #region DEBUG
                                                                        #if DEBUG
                                    Console.WriteLine("remove point with coordinate x = {0}, y = {1}", annotation.X, annotation.Y);
                                                                        #endif
                                    #endregion

                                    //удаление центра кластера
                                    plot.Model.Annotations.Remove(annotation);
                                    break;
                                }
                            }
                        }
                    }

                    //Отмечаем новые кластеры на графике
                    for (int i = 0; i < clusterCenters.Count; i++)
                    {
                        List <double> clusterCenter = clusterCenters[i];
                        bool          isExists      = false;
                        foreach (PointAnnotation annotation in plot.Model.Annotations)
                        {
                            // todo: разобраться со сравнением флоат-пойнт чисел
                            if (annotation.X == clusterCenter[0] && annotation.Y == clusterCenter[1])
                            {
                                //если центр кластера с такими координатами существует, помечаем его на графике как центр кластера
                                UIUtils.MarkClusterCenter(annotation, colorValues[i]);
                                isExists = true;
                                break;
                            }
                        }
                        //если центр кластера с такими координатами не существует, создаём на графике новую точку и помечаем её как центр кластера
                        if (!isExists)
                        {
                            PointAnnotation pointAnnotation = new PointAnnotation {
                                X = clusterCenter[0], Y = clusterCenter[1]
                            };
                            UIUtils.MarkClusterCenter(pointAnnotation, colorValues[i]);
                            plot.Model.Annotations.Add(pointAnnotation);

                            #region DEBUG
                                                        #if DEBUG
                            Console.WriteLine("add center with coordinate x = {0}, y = {1}", pointAnnotation.X, pointAnnotation.Y);
                                                        #endif
                            #endregion
                        }
                    }
                }

                plot.InvalidatePlot();
                //Thread.Sleep(1000);
                iteration++;
            }
        }
Example #4
0
        void UpdateChart()
        {
            if (boxRestartDates.SelectedIndex == -1)
            {
                return;
            }
            if (boxKeywords.SelectedIndex == -1)
            {
                return;
            }

            plotModel.Series.Clear();
            plotModel.Annotations.Clear();
            plotHisto.Series.Clear();
            plotHistoTotal.Series.Clear();

            plotModel.Title = boxKeywords.Text.ToUpper();

            gridData.Rows.Clear();

            plotModel.Series.Add(new LineSeries
            {
                LineStyle    = LineStyle.None,
                MarkerType   = MarkerType.Circle,
                MarkerFill   = Color.Orange.ToOxyColor(),
                MarkerStroke = Color.Black.ToOxyColor(),
                MarkerSize   = 3
            });

            int    timeStep = boxRestartDates.SelectedIndex;
            string keyword  = "W" + boxKeywords.Text;

            double maxValue = 0;
            double absValue = 0;
            double relValue = 0;

            int over20 = 0;
            int over10 = 0;
            int less10 = 0;
            int sum    = 0;

            double sumOver20 = 0;
            double sumOver10 = 0;
            double sumLess10 = 0;

            foreach (Vector well in selectedVectors)
            {
                var simIndex  = well.Data.FirstOrDefault(c => c.keyword == keyword).index;
                var simValue  = model.GetParamAtIndex(simIndex, timeStep);
                var histIndex = well.Data.FirstOrDefault(c => c.keyword == keyword + "H").index;
                var histValue = model.GetParamAtIndex(histIndex, timeStep);

                if (histValue != 0.00)
                {
                    int row = gridData.Rows.Add();

                    gridData[0, row].Value = well.Name;
                    gridData[1, row].Value = simValue;
                    gridData[2, row].Value = histValue;

                    absValue = simValue - histValue;
                    relValue = 100 * (simValue - histValue) / histValue;

                    gridData[3, row].Value = absValue;
                    gridData[4, row].Value = relValue;

                    // Критерии

                    if (activeCondition == TypeCondition.Relative)
                    {
                        if (Math.Abs(relValue) <= firstCondition[0])
                        {
                            sumLess10 += histValue;
                            less10++;
                        }

                        if ((Math.Abs(relValue) > firstCondition[0]) && (Math.Abs(relValue) <= secondCondition[0]))
                        {
                            sumOver10 += histValue;
                            over10++;
                        }

                        if (Math.Abs(relValue) > secondCondition[0])
                        {
                            sumOver20 += histValue;
                            over20++;
                        }
                    }

                    if (activeCondition == TypeCondition.Absolute)
                    {
                        if (Math.Abs(absValue) <= firstCondition[1])
                        {
                            sumLess10 += histValue;
                            less10++;
                        }

                        if ((Math.Abs(absValue) > firstCondition[1]) && (Math.Abs(absValue) <= secondCondition[1]))
                        {
                            sumOver10 += histValue;
                            over10++;
                        }

                        if (Math.Abs(absValue) > secondCondition[1])
                        {
                            sumOver20 += histValue;
                            over20++;
                        }
                    }
                    //
                    sum = less10 + over10 + over20;

                    var pointAnnotation = new OxyPlot.Annotations.PointAnnotation
                    {
                        Fill            = Color.Orange.ToOxyColor(),
                        StrokeThickness = 1,
                        Stroke          = Color.Black.ToOxyColor(),
                        X        = Convert.ToDouble(simValue),
                        Y        = Convert.ToDouble(histValue),
                        Text     = well.Name,
                        FontSize = 9
                    };

                    plotModel.Annotations.Add(pointAnnotation);
                }

                if (simValue > maxValue)
                {
                    maxValue = simValue;
                }
                if (histValue > maxValue)
                {
                    maxValue = histValue;
                }
            }

            if (sum > 0)
            {
                // Линия хорошей адаптации

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Red.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                ((LineSeries)plotModel.Series[1]).Points.Add(new DataPoint(0, 0));
                ((LineSeries)plotModel.Series[1]).Points.Add(new DataPoint(maxValue, maxValue));

                // Линия по первому условию

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Green.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Green.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Blue.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Blue.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                if (activeCondition == TypeCondition.Relative)
                {
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(maxValue, (100 + firstCondition[0]) * 0.01 * maxValue));

                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(maxValue, (100 - firstCondition[0]) * 0.01 * maxValue));

                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(maxValue, (100 + secondCondition[0]) * 0.01 * maxValue));

                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(maxValue, (100 - secondCondition[0]) * 0.01 * maxValue));

                    plotHisto.Axes[0].Title      = "Relative Deviation";
                    plotHistoTotal.Axes[0].Title = "Relative Deviation";

                    ((CategoryAxis)plotHisto.Axes[0]).ItemsSource      = new[] { "<" + firstCondition[0] + "%", firstCondition[0] + "-" + secondCondition[0] + " %", ">" + secondCondition[0] + "%" };
                    ((CategoryAxis)plotHistoTotal.Axes[0]).ItemsSource = new[] { "<" + firstCondition[0] + "%", firstCondition[0] + "-" + secondCondition[0] + " %", ">" + secondCondition[0] + "%" };
                }

                if (activeCondition == TypeCondition.Absolute)
                {
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(0, firstCondition[1]));
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(maxValue, maxValue + firstCondition[1]));

                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(0, -firstCondition[1]));
                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(maxValue, maxValue - firstCondition[1]));

                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(0, secondCondition[1]));
                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(maxValue, maxValue + secondCondition[1]));

                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(0, -secondCondition[1]));
                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(maxValue, maxValue - secondCondition[1]));

                    plotHisto.Axes[0].Title      = "Absolute Deviation";
                    plotHistoTotal.Axes[0].Title = "Absolute Deviation";
                    ((CategoryAxis)plotHisto.Axes[0]).ItemsSource      = new[] { "<" + firstCondition[1], firstCondition[1] + "-" + secondCondition[1], ">" + secondCondition[1] };
                    ((CategoryAxis)plotHistoTotal.Axes[0]).ItemsSource = new[] { "<" + firstCondition[1], firstCondition[1] + "-" + secondCondition[1], ">" + secondCondition[1] };
                }

                plotHisto.Series.Add(new OxyPlot.Series.BarSeries
                {
                    BaseValue         = 0,
                    FillColor         = OxyColor.FromArgb(255, 255, 120, 0),
                    LabelPlacement    = LabelPlacement.Middle,
                    LabelFormatString = "{0}"
                });

                ((BarSeries)plotHisto.Series[0]).Items.Add(new BarItem {
                    Value = less10
                });
                ((BarSeries)plotHisto.Series[0]).Items.Add(new BarItem {
                    Value = over10
                });
                ((BarSeries)plotHisto.Series[0]).Items.Add(new BarItem {
                    Value = over20
                });


                plotHistoTotal.Series.Add(new OxyPlot.Series.BarSeries
                {
                    BaseValue         = 0,
                    FillColor         = OxyColor.FromArgb(255, 255, 120, 0),
                    LabelPlacement    = LabelPlacement.Middle,
                    LabelFormatString = "{0:.00}"
                });

                ((BarSeries)plotHistoTotal.Series[0]).Items.Add(new BarItem {
                    Value = sumLess10
                });
                ((BarSeries)plotHistoTotal.Series[0]).Items.Add(new BarItem {
                    Value = sumOver10
                });
                ((BarSeries)plotHistoTotal.Series[0]).Items.Add(new BarItem {
                    Value = sumOver20
                });
            }
            plotModel.InvalidatePlot(true);
            plotHisto.InvalidatePlot(true);
            plotHistoTotal.InvalidatePlot(true);
        }
Example #5
0
        void UpdateData()
        {
            if (plotModel == null)
            {
                return;
            }

            gridData.Rows.Clear();
            plotModel.Series.Clear();
            plotModel.Annotations.Clear();
            plotHisto.Series.Clear();

            int    step    = boxRestart.SelectedIndex;
            string keyword = listKeywords.SelectedItem.ToString();

            //
            // _ = new List<Tuple<string, float, float>>();

            List <Tuple <string, float, float> > data;

            if (listGroups.SelectedItem.ToString() == "(All)")
            {
                data = model.GetDataByKeywordAndDate(keyword, step);
            }
            else
            {
                string selected_pad = listGroups.SelectedItem.ToString();
                data = model.GetDataByPadKeywordAndDate(selected_pad, keyword, step);
            }

            plotModel.Title = keyword.ToUpper();

            int row = -1;

            int   over20   = 0;
            int   over10   = 0;
            int   less10   = 0;
            int   sum      = 0;
            float max      = 0;
            float relvalue = 0;
            float absvalue = 0;

            plotModel.Series.Add(new LineSeries
            {
                LineStyle    = LineStyle.None,
                MarkerType   = MarkerType.Circle,
                MarkerFill   = Color.Orange.ToOxyColor(),
                MarkerStroke = Color.Black.ToOxyColor(),
                MarkerSize   = 3
            });


            foreach (Tuple <string, float, float> item in data)
            {
                if ((item.Item2 != 0.00) && (item.Item3 != 0.00))
                {
                    row = gridData.Rows.Add();

                    gridData[0, row].Value = item.Item1;
                    gridData[1, row].Value = item.Item2;
                    gridData[2, row].Value = item.Item3;

                    absvalue = item.Item2 - item.Item3;
                    relvalue = 100 * (item.Item2 - item.Item3) / item.Item3;

                    gridData[3, row].Value = absvalue;
                    gridData[4, row].Value = relvalue;

                    // Критерии

                    if (ActiveCondition == TypeCondition.Relative)
                    {
                        if (Math.Abs(relvalue) <= FirstCond)
                        {
                            less10++;
                        }
                        if ((Math.Abs(relvalue) > FirstCond) && (Math.Abs(relvalue) <= SecondCond))
                        {
                            over10++;
                        }
                        if (Math.Abs(relvalue) > SecondCond)
                        {
                            over20++;
                        }
                    }

                    if (ActiveCondition == TypeCondition.Absolute)
                    {
                        if (Math.Abs(absvalue) <= FirstCond)
                        {
                            less10++;
                        }
                        if ((Math.Abs(absvalue) > FirstCond) && (Math.Abs(absvalue) <= SecondCond))
                        {
                            over10++;
                        }
                        if (Math.Abs(absvalue) > SecondCond)
                        {
                            over20++;
                        }
                    }

                    if (item.Item2 > max)
                    {
                        max = item.Item2;
                    }
                    if (item.Item3 > max)
                    {
                        max = item.Item3;
                    }
                    //


                    // Точки на графике

                    var pointAnnotation1 = new OxyPlot.Annotations.PointAnnotation();
                    pointAnnotation1.Fill            = Color.Orange.ToOxyColor();
                    pointAnnotation1.StrokeThickness = 1;
                    pointAnnotation1.Stroke          = Color.Black.ToOxyColor();
                    pointAnnotation1.X        = Convert.ToDouble(item.Item2);
                    pointAnnotation1.Y        = Convert.ToDouble(item.Item3);
                    pointAnnotation1.Text     = item.Item1;
                    pointAnnotation1.FontSize = 9;
                    plotModel.Annotations.Add(pointAnnotation1);
                }
            }
            sum = less10 + over10 + over20;

            if (sum > 0)
            {
                // Линия хорошей адаптации

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Red.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                ((LineSeries)plotModel.Series[1]).Points.Add(new DataPoint(0, 0));
                ((LineSeries)plotModel.Series[1]).Points.Add(new DataPoint(max, max));

                // Линия по первому условию

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Green.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Green.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Blue.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                plotModel.Series.Add(new LineSeries
                {
                    LineStyle  = LineStyle.Dot,
                    Color      = Color.Blue.ToOxyColor(),
                    MarkerType = MarkerType.None,
                });

                if (ActiveCondition == TypeCondition.Relative)
                {
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(max, (100 + FirstCond) * 0.01 * max));

                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(max, (100 - FirstCond) * 0.01 * max));

                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(max, (100 + SecondCond) * 0.01 * max));

                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(0, 0));
                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(max, (100 - SecondCond) * 0.01 * max));

                    plotHisto.Axes[0].Title = "Relative Deviation";
                    ((CategoryAxis)plotHisto.Axes[0]).ItemsSource = new[] { "<" + FirstCond + "%", FirstCond + "-" + SecondCond + " %", ">" + SecondCond + "%" };
                }

                if (ActiveCondition == TypeCondition.Absolute)
                {
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(0, FirstCond));
                    ((LineSeries)plotModel.Series[2]).Points.Add(new DataPoint(max, max + FirstCond));

                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(0, -FirstCond));
                    ((LineSeries)plotModel.Series[3]).Points.Add(new DataPoint(max, max - FirstCond));

                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(0, SecondCond));
                    ((LineSeries)plotModel.Series[4]).Points.Add(new DataPoint(max, max + SecondCond));

                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(0, -SecondCond));
                    ((LineSeries)plotModel.Series[5]).Points.Add(new DataPoint(max, max - SecondCond));

                    plotHisto.Axes[0].Title = "Absolute Deviation";
                    ((CategoryAxis)plotHisto.Axes[0]).ItemsSource = new[] { "<" + FirstCond, FirstCond + "-" + SecondCond, ">" + SecondCond };
                }

                plotHisto.Series.Add(new BarSeries
                {
                    FillColor = OxyColor.FromArgb(255, 255, 120, 0),
                });

                ((BarSeries)plotHisto.Series[0]).Items.Add(new BarItem {
                    Value = less10
                });
                ((BarSeries)plotHisto.Series[0]).Items.Add(new BarItem {
                    Value = over10
                });
                ((BarSeries)plotHisto.Series[0]).Items.Add(new BarItem {
                    Value = over20
                });
            }

            plotModel.InvalidatePlot(true);
            plotHisto.InvalidatePlot(true);
        }
        /// <summary>
        /// Кластеризация Fuzzy C-Means
        /// </summary>
        /// <param name="plot">Модель графика OxyPlot</param>
        /// <param name="label">Label для показа информации о номере итерации</param>
        /// <param name="numberOfClusters">Число кластеров</param>
        /// <param name="fuzzificationParameter">параметр фаззификации</param>
        public static void DoClusteringByFuzzyCMeans(PlotView plot, Label label, int numberOfClusters, double fuzzificationParameter)
        {
            if (plot.Model == null)
            {
                return;
            }

            //координаты точек
            List <List <double> > coordinates = new List <List <double> >();

            //заполнении информации о координатах точек
            foreach (PointAnnotation annotation in plot.Model.Annotations)
            {
                List <double> pointCoordinates = new List <double> {
                    annotation.X, annotation.Y
                };
                coordinates.Add(pointCoordinates);
            }

            Random random = new Random();

            byte[] bgrColorComponents = new byte[3];
            //цвета кластеров, выбираются случайно
            Dictionary <List <double>, OxyColor> clusterColors = new Dictionary <List <double>, OxyColor>();

            //первоначальная генерация центров кластеров
            List <List <double> > clusterCenters = AlgorithmsUtils.MakeInitialSeeds(coordinates, numberOfClusters);

            foreach (List <double> clusterCenter in clusterCenters)
            {
                foreach (PointAnnotation annotation in plot.Model.Annotations)
                {
                    // todo: разобраться со сравнением флоат-пойнт чисел
                    if (annotation.X == clusterCenter[0] && annotation.Y == clusterCenter[1])
                    {
                        random.NextBytes(bgrColorComponents);
                        //отметим на графике центры кластеров
                        UIUtils.MarkClusterCenter(annotation, OxyColor.FromRgb(bgrColorComponents[0], bgrColorComponents[1], bgrColorComponents[2]));
                        clusterColors.Add(clusterCenter, annotation.Fill);

                        #region DEBUG
#if DEBUG
                        Console.WriteLine("Inital cluster center x = {0}, y = {1}", annotation.X, annotation.Y);
#endif
                        #endregion
                    }
                }
            }

            bool stop = false;
            Dictionary <List <double>, List <double> > clusters = null;

            //матрица членства - Отображение "координаты точки" -> "значения функции членства точки во всех кластерах"
            Dictionary <List <double>, List <double> > membershipMatrix = null;

            int iteration = 0;

            //цикл продолжается пока меняются координаты центров кластеров
            while (!stop)
            {
                #region DEBUG
#if DEBUG
                Console.WriteLine("Iteration = {0}", iteration);
#endif
                #endregion

                label.Content = "Iteration " + iteration;

                //отображение из координат точки в координаты центра кластера
                clusters = MakeFuzzyClusters(coordinates, clusterCenters, fuzzificationParameter, out membershipMatrix);
                foreach (KeyValuePair <List <double>, List <double> > pair in clusters)
                {
                    foreach (PointAnnotation annotation in plot.Model.Annotations)
                    {
                        // todo: разобраться со сравнением флоат-пойнт чисел
                        if (annotation.X == pair.Key[0] && annotation.Y == pair.Key[1])
                        {
                            //закрашиваем точку цветом кластера
                            annotation.Fill = clusterColors[pair.Value];
                        }
                    }
                }

                //отображение значений матрицы членства для каждой точки на графике
                foreach (KeyValuePair <List <double>, List <double> > pair in membershipMatrix)
                {
                    foreach (PointAnnotation annotation in plot.Model.Annotations)
                    {
                        // todo: разобраться со сравнением флоат-пойнт чисел
                        if (annotation.X == pair.Key[0] && annotation.Y == pair.Key[1])
                        {
                            String tooltip = "";

                            for (int i = 0; i < pair.Value.Count; i++)
                            {
                                double value = pair.Value[i];
                                tooltip += "Cluster " + i + ": Value: " + Math.Round(value, 2) + "\n";
                            }

                            annotation.ToolTip = tooltip;
                        }
                    }
                }

                List <List <double> > oldClusterCenters = clusterCenters;
                //пересчёт центров кластеров
                clusterCenters = RecalculateCoordinateOfFuzzyClusterCenters(clusterCenters, membershipMatrix, fuzzificationParameter);

                Dictionary <List <double>, List <double> > distancesToClusterCenters = AlgorithmsUtils.CalculateDistancesToClusterCenters(coordinates, clusterCenters);
                Dictionary <List <double>, List <double> > newMembershipMatrix       = CreateMembershipMatrix(distancesToClusterCenters, fuzzificationParameter);

                List <List <double> > differences = ListUtils.CreateDifferencesMatrix(newMembershipMatrix.Values.ToList(), membershipMatrix.Values.ToList());
                //если координаты центров кластеров не изменились, выходим из цикла
                double maxElement = ListUtils.GetMaxElement(differences);

                #region DEBUG
#if DEBUG
                Console.WriteLine("Max element: {0}", maxElement);
#endif
                #endregion

                if (maxElement < 0.001)
                {
                    stop = true;
                }
                //если координаты центров кластеров поменялись изменились, пересчитываем кластеры
                else
                {
                    List <OxyColor> colorValues = clusterColors.Values.ToList();
                    clusterColors.Clear();
                    for (int i = 0; i < clusterCenters.Count; i++)
                    {
                        clusterColors.Add(clusterCenters[i], colorValues[i]);
                    }

                    //удаление отображения всех центров кластеров
                    foreach (PointAnnotation annotation in plot.Model.Annotations)
                    {
                        annotation.Shape = MarkerType.Circle;
                        annotation.Size  = 4;
                    }

                    //проверка на потенциально не существующие центры кластеров
                    foreach (List <double> oldClusterCenter in oldClusterCenters)
                    {
                        bool isClusterCenterDataPoint = false;
                        foreach (List <double> coordinate in coordinates)
                        {
                            // todo: разобраться со сравнением флоат-пойнт чисел
                            if (oldClusterCenter[0] == coordinate[0] && oldClusterCenter[1] == coordinate[1])
                            {
                                #region DEBUG
#if DEBUG
                                Console.WriteLine("ex-center x = {0}, y = {1}", oldClusterCenter[0], oldClusterCenter[1]);
#endif
                                #endregion

                                isClusterCenterDataPoint = true;
                                break;
                            }
                        }
                        //если центр кластера не является точкой данных
                        if (!isClusterCenterDataPoint)
                        {
                            foreach (PointAnnotation annotation in plot.Model.Annotations)
                            {
                                // todo: разобраться со сравнением флоат-пойнт чисел
                                if (annotation.X == oldClusterCenter[0] && annotation.Y == oldClusterCenter[1])
                                {
                                    #region DEBUG
#if DEBUG
                                    Console.WriteLine("remove center with coordinate x = {0}, y = {1}", annotation.X, annotation.Y);
#endif
                                    #endregion

                                    //удаление центра кластера
                                    plot.Model.Annotations.Remove(annotation);
                                    break;
                                }
                            }
                        }
                    }

                    //Отмечаем новые кластеры на графике
                    for (int i = 0; i < clusterCenters.Count; i++)
                    {
                        List <double> clusterCenter = clusterCenters[i];
                        bool          isExists      = false;
                        foreach (PointAnnotation annotation in plot.Model.Annotations)
                        {
                            // todo: разобраться со сравнением флоат-пойнт чисел
                            if (annotation.X == clusterCenter[0] && annotation.Y == clusterCenter[1])
                            {
                                //если центр кластера с такими координатами существует, помечаем его на графике как центр кластера
                                UIUtils.MarkClusterCenter(annotation, colorValues[i]);
                                isExists = true;
                                break;
                            }
                        }
                        //если центр кластера с такими координатами не существует, создаём на графике новую точку и помечаем её как центр кластера
                        if (!isExists)
                        {
                            PointAnnotation pointAnnotation = new PointAnnotation {
                                X = clusterCenter[0], Y = clusterCenter[1]
                            };
                            UIUtils.MarkClusterCenter(pointAnnotation, colorValues[i]);
                            plot.Model.Annotations.Add(pointAnnotation);

                            #region DEBUG
#if DEBUG
                            Console.WriteLine("add center with coordinate x = {0}, y = {1}", pointAnnotation.X, pointAnnotation.Y);
#endif
                            #endregion
                        }
                    }
                }

                plot.InvalidatePlot();
                iteration++;
            }
        }