Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.MultiObjectiveTestFunctions/HeuristicLab.Problems.MultiObjectiveTestFunctions/3.3/Drawings/MOQualitiesScatterPlotView.cs @ 13620

Last change on this file since 13620 was 13620, checked in by bwerth, 8 years ago

#1087 regorganized testfunctions, added view for qualities

File size: 11.5 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Drawing;
4using System.Data;
5using System.Linq;
6using System.Text;
7using System.Windows.Forms;
8using HeuristicLab.MainForm;
9using System.Windows.Forms.DataVisualization.Charting;
10using HeuristicLab.Encodings.RealVectorEncoding;
11
12namespace HeuristicLab.Problems.MultiObjectiveTestFunctions.Drawings {
13  [View("Scatter Plot")]
14  [Content(typeof(IMOQualities))]
15  public partial class MOQualitiesScatterPlotView : MOQualitiesView {
16
17    private const string QUALITIES = "Qualities";
18    private const string PARETO_FRONT = "Best Known Pareto Front";
19    //private const string TEST_SERIES = "Test samples";
20    private int xDim = 0;
21    private int yDim = 1;
22    int objectives = -1;
23    bool optimalKnown = true;
24
25    public new IMOQualities Content {
26      get { return (IMOQualities)base.Content; }
27      set { base.Content = value; }
28    }
29
30    public MOQualitiesScatterPlotView()
31        : base() {
32      InitializeComponent();
33
34      this.chart.Series.Add(QUALITIES);
35      this.chart.Series[QUALITIES].LegendText = QUALITIES;
36      this.chart.Series[QUALITIES].ChartType = SeriesChartType.FastPoint;
37
38      this.chart.Series.Add(PARETO_FRONT);
39      this.chart.Series[PARETO_FRONT].LegendText = PARETO_FRONT;
40      this.chart.Series[PARETO_FRONT].ChartType = SeriesChartType.FastPoint;
41
42      this.chart.TextAntiAliasingQuality = TextAntiAliasingQuality.High;
43      this.chart.AxisViewChanged += new EventHandler<System.Windows.Forms.DataVisualization.Charting.ViewEventArgs>(chart_AxisViewChanged);
44
45      //configure axis
46      this.chart.CustomizeAllChartAreas();
47      this.chart.ChartAreas[0].AxisX.Title = "XAxis: Objective " + xDim;
48      this.chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
49      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
50      this.chart.ChartAreas[0].CursorX.Interval = 1;
51      this.chart.ChartAreas[0].CursorY.Interval = 1;
52
53      this.chart.ChartAreas[0].AxisY.Title = "YAxis: Objective " + yDim;
54      this.chart.ChartAreas[0].CursorY.IsUserSelectionEnabled = true;
55      this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = true;
56      this.chart.ChartAreas[0].AxisY.IsStartedFromZero = true;
57    }
58
59    protected override void RegisterContentEvents() {
60      base.RegisterContentEvents();
61      this.chart.GetToolTipText += new System.EventHandler<ToolTipEventArgs>(this.Chart_GetToolTipText);
62     
63    }
64    protected override void DeregisterContentEvents() {
65      base.DeregisterContentEvents();
66      this.chart.GetToolTipText -= new System.EventHandler<ToolTipEventArgs>(this.Chart_GetToolTipText);
67    }
68
69
70    private void Chart_GetToolTipText(object sender, ToolTipEventArgs e) {
71
72      // Check selected chart element and set tooltip text
73      if (e.HitTestResult.ChartElementType == ChartElementType.DataPoint) {
74        int i = e.HitTestResult.PointIndex;
75        StringBuilder toolTippText = new StringBuilder();
76        DataPoint qp = e.HitTestResult.Series.Points[i];
77        toolTippText.Append("Objective " + xDim + " = " + qp.XValue+ "\n");
78        toolTippText.Append("Objective " + yDim + " = " + qp.YValues[0]);
79
80        Series s = e.HitTestResult.Series;
81        if (s.Equals(this.chart.Series[QUALITIES])) {
82          RealVector dp = Content.Solutions[i].RealVector();
83          toolTippText.Append("\nSolution: {");
84          for (int j = 0; j < dp.Length; j++) {
85            toolTippText.Append(dp[j]);
86            toolTippText.Append(";");
87          }
88          toolTippText.Remove(toolTippText.Length - 1, 1);
89          toolTippText.Append("}");
90          e.Text = toolTippText.ToString();
91        }
92
93
94      }
95    }
96
97    protected override void OnContentChanged() {
98      base.OnContentChanged();
99      if (Content == null) return;
100      if (objectives != Content.Objectives) {
101        AddMenuItems();
102        objectives = Content.Objectives;
103      }
104      if(Content.ParetoFront == null && optimalKnown) {
105        Series s =  this.chart.Series[PARETO_FRONT];
106        this.chart.Series.Remove(s);
107        optimalKnown = false;
108      } else if(Content.ParetoFront != null && !optimalKnown) {
109        this.chart.Series.Add(PARETO_FRONT);
110        this.chart.Series[PARETO_FRONT].LegendText = PARETO_FRONT;
111        this.chart.Series[PARETO_FRONT].ChartType = SeriesChartType.FastPoint;
112        optimalKnown = true;
113      }
114      UpdateChart();
115    }
116
117    private void UpdateChart() {
118      if (InvokeRequired) Invoke((Action)UpdateChart);
119      else {
120        if (Content != null) {
121          this.UpdateSeries();
122          if (!this.chart.Series.Any(s => s.Points.Count > 0))
123            this.ClearChart();
124        }
125      }
126    }
127
128    private void UpdateCursorInterval() {
129      var estimatedValues = this.chart.Series[QUALITIES].Points.Select(x => x.XValue).DefaultIfEmpty(1.0);
130      var targetValues = this.chart.Series[QUALITIES].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
131      double estimatedValuesRange = estimatedValues.Max() - estimatedValues.Min();
132      double targetValuesRange = targetValues.Max() - targetValues.Min();
133      double interestingValuesRange = Math.Min(Math.Max(targetValuesRange, 1.0), Math.Max(estimatedValuesRange, 1.0));
134      double digits = (int)Math.Log10(interestingValuesRange) - 3;
135      double zoomInterval = Math.Max(Math.Pow(10, digits), 10E-5);
136      this.chart.ChartAreas[0].CursorX.Interval = zoomInterval;
137      this.chart.ChartAreas[0].CursorY.Interval = zoomInterval;
138
139      this.chart.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = zoomInterval;
140      this.chart.ChartAreas[0].AxisY.ScaleView.SmallScrollSize = zoomInterval;
141
142      this.chart.ChartAreas[0].AxisX.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Number;
143      this.chart.ChartAreas[0].AxisX.ScaleView.SmallScrollMinSize = zoomInterval;
144      this.chart.ChartAreas[0].AxisY.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Number;
145      this.chart.ChartAreas[0].AxisY.ScaleView.SmallScrollMinSize = zoomInterval;
146
147      if (digits < 0) {
148        this.chart.ChartAreas[0].AxisX.LabelStyle.Format = "F" + (int)Math.Abs(digits);
149        this.chart.ChartAreas[0].AxisY.LabelStyle.Format = "F" + (int)Math.Abs(digits);
150      } else {
151        this.chart.ChartAreas[0].AxisX.LabelStyle.Format = "F0";
152        this.chart.ChartAreas[0].AxisY.LabelStyle.Format = "F0";
153      }
154    }
155
156
157    private double max = 1;
158    private double min = 0;
159    private void UpdateSeries() {
160      if (InvokeRequired) Invoke((Action)UpdateSeries);
161      else {
162        this.max = 1;
163        this.min = 0;
164
165        if (this.chart.Series[QUALITIES].Points.Count > 0 ) {
166          fillSeries(Content.Qualities, this.chart.Series[QUALITIES]);
167        }
168        if (optimalKnown && this.chart.Series[PARETO_FRONT].Points.Count > 0) {
169          fillSeries(Content.ParetoFront, this.chart.Series[PARETO_FRONT]);
170        }
171
172       // double max = this.max;
173       // double min = this.min;
174
175        max = max + 0.2 * Math.Abs(max);
176        min = min - 0.2 * Math.Abs(min);
177
178        double interestingValuesRange = max - min;
179        int digits = Math.Max(0, 3 - (int)Math.Log10(interestingValuesRange));
180
181        max = Math.Round(max, digits);
182        min = Math.Round(min, digits);
183
184        this.chart.ChartAreas[0].AxisX.Maximum = max;
185        this.chart.ChartAreas[0].AxisX.Minimum = min;
186        this.chart.ChartAreas[0].AxisY.Maximum = max;
187        this.chart.ChartAreas[0].AxisY.Minimum = min;
188        UpdateCursorInterval();
189      }
190    }
191
192    private void ClearChart() {
193      this.chart.Series[QUALITIES].Points.Clear();
194      if(optimalKnown) this.chart.Series[PARETO_FRONT].Points.Clear();
195    }
196
197    private void ToggleSeriesData(Series series) {
198      if (series.Points.Count > 0) {  //checks if series is shown
199        series.Points.Clear();
200      } else if (Content != null) {
201        switch (series.Name) {
202          case PARETO_FRONT:
203            fillSeries(Content.ParetoFront, this.chart.Series[PARETO_FRONT]);
204            break;
205          case QUALITIES:
206            fillSeries(Content.Qualities, this.chart.Series[QUALITIES]);
207            break;
208        }
209      }
210    }
211
212    private void chart_MouseDown(object sender, MouseEventArgs e) {
213      HitTestResult result = chart.HitTest(e.X, e.Y);
214      if (result.ChartElementType == ChartElementType.LegendItem) {
215        this.ToggleSeriesData(result.Series);
216      }
217
218    }
219
220    private void chart_MouseMove(object sender, MouseEventArgs e) {
221      HitTestResult result = chart.HitTest(e.X, e.Y);
222      if (result.ChartElementType == ChartElementType.LegendItem)
223        this.Cursor = Cursors.Hand;
224      else
225        this.Cursor = Cursors.Default;
226    }
227
228    private void chart_AxisViewChanged(object sender, System.Windows.Forms.DataVisualization.Charting.ViewEventArgs e) {
229      this.chart.ChartAreas[0].AxisX.ScaleView.Size = e.NewSize;
230      this.chart.ChartAreas[0].AxisY.ScaleView.Size = e.NewSize;
231    }
232
233    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
234      e.LegendItems[0].Cells[1].ForeColor = this.chart.Series[QUALITIES].Points.Count == 0 ? Color.Gray : Color.Black;
235      if (optimalKnown) {
236      e.LegendItems[1].Cells[1].ForeColor = this.chart.Series[PARETO_FRONT].Points.Count == 0 ? Color.Gray : Color.Black;
237    }
238      //  e.LegendItems[2].Cells[1].ForeColor = this.chart.Series[TEST_SERIES].Points.Count == 0 ? Color.Gray : Color.Black;
239    }
240
241    private void AddMenuItems() {
242      chooseDimensionToolStripMenuItem.DropDownItems.Clear();
243      chooseYDimensionToolStripMenuItem.DropDownItems.Clear();
244      if (Content == null) { return; }
245      for (int i = 0; i < Content.Objectives; i++) {
246        //add Menu Points
247        ToolStripMenuItem xItem = makeMenuItem("X", i);
248        ToolStripMenuItem yItem = makeMenuItem("Y", i); ;
249        xItem.Click += new System.EventHandler(this.XMenu_Click);
250        yItem.Click += new System.EventHandler(this.YMenu_Click);
251        chooseDimensionToolStripMenuItem.DropDownItems.Add(xItem);
252        chooseYDimensionToolStripMenuItem.DropDownItems.Add(yItem);
253      }
254    }
255
256    private ToolStripMenuItem makeMenuItem(String axis, int i) {
257      ToolStripMenuItem xItem = new ToolStripMenuItem();
258      xItem.Name = "obj" + i;
259      xItem.Size = new System.Drawing.Size(269, 38);
260      xItem.Text = "Objective" + i;
261      return xItem;
262    }
263
264    private void YMenu_Click(object sender, EventArgs e) {
265      ToolStripMenuItem item = (ToolStripMenuItem)sender;
266      yDim = Int32.Parse(item.Name.Remove(0, 3));
267      this.chooseYDimensionToolStripMenuItem.Text = "Objective" + yDim;
268      this.chart.ChartAreas[0].AxisY.Title = "Objective " + yDim;
269      UpdateChart();
270    }
271
272    private void XMenu_Click(object sender, EventArgs e) {
273      ToolStripMenuItem item = (ToolStripMenuItem)sender;
274      xDim = Int32.Parse(item.Name.Remove(0, 3));
275      this.chooseDimensionToolStripMenuItem.Text = "Objective" + xDim;
276      this.chart.ChartAreas[0].AxisX.Title = "Objective " + xDim;
277      UpdateChart();
278    }
279
280    private void fillSeries(IEnumerable<double[]> data, Series series) {
281      series.Points.Clear();
282      foreach (double[] d in data) {   //Assumtion: Columnwise
283        if (d[xDim] > max) max = d[xDim];
284        if (d[yDim] > max) max = d[yDim];
285        if (d[xDim] < min) min = d[xDim];
286        if (d[yDim] < min) min = d[yDim];
287        series.Points.AddXY(d[xDim], d[yDim]);
288      }
289    }
290  }
291}
292
Note: See TracBrowser for help on using the repository browser.