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; } }
/// <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++; } }
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); }
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++; } }