Changeset 571 for trunk/sources/HeuristicLab.CEDMA.Charting/Histogram.cs
- Timestamp:
- 09/14/08 21:18:30 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.CEDMA.Charting/Histogram.cs
r560 r571 1 #region License Information1 #region License Information 2 2 /* HeuristicLab 3 3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL) … … 22 22 using System; 23 23 using System.Collections.Generic; 24 using System.Text; 25 using System.Drawing; 24 26 using System.Linq; 25 using System.Text; 26 using HeuristicLab.Core; 27 using System.Xml; 28 using HeuristicLab.CEDMA.DB.Interfaces; 27 using HeuristicLab.Charting; 28 using System.Windows.Forms; 29 29 30 30 namespace HeuristicLab.CEDMA.Charting { 31 public class Histogram { 32 private int buckets; 33 public int Buckets { 34 get { return buckets; } 35 set { 36 buckets = value; 37 ResetBucketBounds(); 31 public class Histogram : Chart { 32 private static readonly Color defaultColor = Color.Blue; 33 private static readonly Color selectionColor = Color.Red; 34 35 private double minX; 36 private double maxX; 37 private double maxFrequency; 38 private const int N_BUCKETS = 50; 39 private List<Record> records; 40 private ResultList results; 41 private Dictionary<IPrimitive, List<Record>> primitiveToRecordsDictionary; 42 private Dictionary<Record, IPrimitive> recordToPrimitiveDictionary; 43 private Group bars; 44 private double[] limits; 45 private int[] buckets; 46 private string dimension; 47 48 public Histogram(ResultList results, double x1, double y1, double x2, double y2) 49 : this(results, new PointD(x1, y1), new PointD(x2, y2)) { 50 } 51 52 public Histogram(ResultList results, PointD lowerLeft, PointD upperRight) 53 : base(lowerLeft, upperRight) { 54 records = new List<Record>(); 55 primitiveToRecordsDictionary = new Dictionary<IPrimitive, List<Record>>(); 56 recordToPrimitiveDictionary = new Dictionary<Record, IPrimitive>(); 57 this.results = results; 58 foreach(Record r in results.Records) { 59 records.Add(r); 60 r.OnSelectionChanged += new EventHandler(Record_OnSelectionChanged); 61 } 62 results.OnRecordAdded += new EventHandler<RecordAddedEventArgs>(results_OnRecordAdded); 63 results.Changed += new EventHandler(results_Changed); 64 limits = new double[N_BUCKETS - 1]; 65 buckets = new int[N_BUCKETS]; 66 } 67 68 void results_Changed(object sender, EventArgs e) { 69 Repaint(); 70 EnforceUpdate(); 71 } 72 73 void results_OnRecordAdded(object sender, RecordAddedEventArgs e) { 74 lock(records) { 75 e.Record.OnSelectionChanged += new EventHandler(Record_OnSelectionChanged); 76 records.Add(e.Record); 38 77 } 39 78 } 40 79 41 private double[] limit; 42 43 private List<double> values; 44 45 public Histogram(int buckets) { 46 this.buckets = buckets; 47 values = new List<double>(); 80 void Record_OnSelectionChanged(object sender, EventArgs e) { 81 Record r = (Record)sender; 82 IPrimitive primitive; 83 recordToPrimitiveDictionary.TryGetValue(r, out primitive); 84 if(primitive != null) { 85 ((FixedSizeCircle)primitive).UpdateEnabled = false; 86 bars.UpdateEnabled = false; 87 if(r.Selected) { 88 int alpha = primitive.Pen.Color.A; 89 primitive.Pen.Color = Color.FromArgb(alpha, selectionColor); 90 primitive.Brush = primitive.Pen.Brush; 91 primitive.IntoForeground(); 92 } else { 93 int alpha = primitive.Pen.Color.A; 94 primitive.Pen.Color = Color.FromArgb(alpha, defaultColor); 95 primitive.Brush = primitive.Pen.Brush; 96 primitive.IntoBackground(); 97 } 98 ((FixedSizeCircle)primitive).UpdateEnabled = true; 99 bars.UpdateEnabled = true; 100 } 48 101 } 49 102 50 public double LowerValue(int bucketIndex) { 51 return limit[bucketIndex]; 103 public void ShowFrequency(string dimension) { 104 if(this.dimension != dimension) { 105 this.dimension = dimension; 106 ResetViewSize(); 107 Repaint(); 108 ZoomToViewSize(); 109 } 52 110 } 53 111 54 public double UpperValue(int bucketIndex) { 55 return limit[bucketIndex+1]; 112 private void Repaint() { 113 if(dimension == null) return; 114 UpdateEnabled = false; 115 Group.Clear(); 116 primitiveToRecordsDictionary.Clear(); 117 recordToPrimitiveDictionary.Clear(); 118 bars = new Group(this); 119 Group.Add(new Axis(this, 0, 0, AxisType.Both)); 120 UpdateViewSize(0, 0); 121 var values = records.Select(r => r.Get(dimension)).Where( 122 x => !double.IsNaN(x) && !double.IsInfinity(x) && x != double.MinValue && x != double.MaxValue).OrderBy(x => x); 123 IEnumerable<IGrouping<double,double>> frequencies; 124 double bucketSize; 125 if(dimension == Record.TARGET_VARIABLE || dimension == Record.TREE_HEIGHT || dimension == Record.TREE_SIZE) { 126 frequencies = values.GroupBy(x => x); 127 bucketSize = 1.0; 128 } else { 129 double min = values.ElementAt((int)(values.Count() * 0.05)); 130 double max = values.ElementAt((int)(values.Count() * 0.95)); 131 bucketSize = (max - min) / N_BUCKETS; 132 frequencies = values.GroupBy(x => Math.Min(Math.Max(min, Math.Floor((x - min) / bucketSize) * bucketSize + min), max)); 133 } 134 Pen defaultPen = new Pen(defaultColor); 135 Brush defaultBrush = defaultPen.Brush; 136 foreach(IGrouping<double, double> g in frequencies) { 137 double freq = g.Count(); 138 double lower = g.Key; 139 double upper = g.Key+bucketSize; 140 HeuristicLab.Charting.Rectangle bar = new HeuristicLab.Charting.Rectangle(this, lower, 0, upper, freq, defaultPen, defaultBrush); 141 primitiveToRecordsDictionary[bar] = records; 142 if(lower == frequencies.First().Key) bar.ToolTipText = " x < "+upper+" : "+freq; 143 else if(lower ==frequencies.Last().Key) bar.ToolTipText = "x >= "+lower+" : "+freq; 144 else bar.ToolTipText = "x in ["+lower+" .. "+upper+"[ : "+freq; 145 bars.Add(bar); 146 UpdateViewSize(lower, freq); 147 UpdateViewSize(upper, freq); 148 } 149 Group.Add(bars); 150 UpdateEnabled = true; 56 151 } 57 152 58 public int Frequency(int bucketIndex) { 59 return values.Count(x => x >= LowerValue(bucketIndex) && x < UpperValue(bucketIndex)); 153 private void ZoomToViewSize() { 154 if(minX < maxX) { 155 // enlarge view by 5% on each side 156 double width = maxX - minX; 157 minX = minX - width * 0.05; 158 maxX = maxX + width * 0.05; 159 double minY = 0 - maxFrequency * 0.05; 160 double maxY = maxFrequency + maxFrequency * 0.05; 161 ZoomIn(minX, minY, maxX, maxY); 162 } 60 163 } 61 164 62 p ublic void AddValues(IEnumerable<double> xs) {63 values.AddRange(xs.Where(x=>64 !double.IsInfinity(x) && !double.IsNaN(x) && double.MaxValue!=x && double.MinValue !=x));65 ResetBucketBounds();165 private void UpdateViewSize(double x, double freq) { 166 if(x < minX) minX = x; 167 if(x > maxX) maxX = x; 168 if(freq > maxFrequency) maxFrequency = freq; 66 169 } 67 170 68 private void Reset BucketBounds() {69 limit = new double[buckets+1];70 values.Sort();71 double min = values[10];72 double max = values[values.Count-10];171 private void ResetViewSize() { 172 minX = double.PositiveInfinity; 173 maxX = double.NegativeInfinity; 174 maxFrequency = double.NegativeInfinity; 175 } 73 176 74 double step = (max - min) / buckets; 75 double cur = min; 76 for(int i = 0; i < buckets+1; i++) { 77 limit[i] = cur; 78 cur += step; 177 internal List<Record> GetRecords(Point point) { 178 List<Record> records = null; 179 IPrimitive p = bars.GetPrimitive(TransformPixelToWorld(point)); 180 if(p != null) { 181 primitiveToRecordsDictionary.TryGetValue(p, out records); 182 } 183 return records; 184 } 185 186 public override void MouseClick(Point point, MouseButtons button) { 187 if(button == MouseButtons.Left) { 188 List<Record> rs = GetRecords(point); 189 if(rs != null) rs.ForEach(r => r.ToggleSelected()); 190 results.FireChanged(); 191 } else { 192 base.MouseClick(point, button); 79 193 } 80 194 }
Note: See TracChangeset
for help on using the changeset viewer.