Free cookie consent management tool by TermsFeed Policy Generator

source: branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/BoxChart/BoxChartCreator.cs @ 7210

Last change on this file since 7210 was 7210, checked in by epitzer, 12 years ago

#1696: Improve usability of BoxChart creator: add automatic positioning of new chart elements

File size: 8.0 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Drawing;
4using System.Drawing.Drawing2D;
5using System.IO;
6using System.Linq;
7using System.Text;
8using HeuristicLab.Collections;
9using HeuristicLab.Common;
10using HeuristicLab.Core;
11using HeuristicLab.Data;
12using HeuristicLab.Optimization;
13using HeuristicLab.Parameters;
14using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
15using ICSharpCode.SharpZipLib.Zip;
16using System.Drawing.Imaging;
17
18namespace HeuristicLab.Analysis.FitnessLandscape.BoxCharts {
19
20  [Item("Box Chart Creator", "Visualizes essential run information by creating an overview chart.")]
21  [StorableClass]
22  public class BoxChartCreator : ParameterizedNamedItem, IRunCollectionModifier {
23
24    public enum AppendModes { None, Horizontal, Vertical };
25
26    #region Parameters
27    public ValueParameter<StringValue> ChartNameParameter {
28      get { return (ValueParameter<StringValue>)Parameters["ChartName"]; }
29    }
30    public ValueParameter<CheckedItemList<IBoxChartElementGenerator>> ElementsParameter {
31      get { return (ValueParameter<CheckedItemList<IBoxChartElementGenerator>>)Parameters["Elements"]; }
32    }
33    public ValueParameter<IntValue> SizeParameter {
34      get { return (ValueParameter<IntValue>)Parameters["Size"]; }
35    }
36    public ValueParameter<IntValue> PaddingParameter {
37      get { return (ValueParameter<IntValue>) Parameters["Padding"]; }
38    }
39    public ValueParameter<StringValue> ZipFileNameParameter {
40      get { return (ValueParameter<StringValue>) Parameters["ZipFileName"]; }
41    }
42    public ConstrainedValueParameter<StringValue> AppendModeParameter {
43      get { return (ConstrainedValueParameter<StringValue>) Parameters["AppendMode"]; }
44    }
45    #endregion
46
47    #region Parameter Values
48    protected string ChartName { get { return ChartNameParameter.Value.Value; } }
49    protected string ZipFileName { get { return ZipFileNameParameter.Value.Value; } }
50    protected int Size { get { return SizeParameter.Value.Value; } }
51    protected int Padding { get { return PaddingParameter.Value.Value; } }
52    protected AppendModes AppendMode { get { return (AppendModes)Enum.Parse(typeof(AppendModes), AppendModeParameter.Value.Value); } }
53      protected List<IBoxChartElementGenerator> Generators {
54      get {
55        return ElementsParameter.Value.CheckedItems.Select(i => i.Value).ToList();
56      }
57    }
58    #endregion
59
60    #region Construction & Cloning
61    [StorableConstructor]
62    protected BoxChartCreator(bool deserializing) : base(deserializing) { }
63    protected BoxChartCreator(BoxChartCreator original, Cloner cloner) : base(original, cloner) {
64      RegisterEvents();
65    }
66    public BoxChartCreator() {
67      Parameters.Add(new ValueParameter<StringValue>("ChartName", "The result name of the chart.", new StringValue("Chart")));
68      Parameters.Add(new ValueParameter<CheckedItemList<IBoxChartElementGenerator>>("Elements", "List of patient chart element generators.", new CheckedItemList<IBoxChartElementGenerator>()));
69      Parameters.Add(new ValueParameter<IntValue>("Size", "The size of one box in pixels.", new IntValue(50)));
70      Parameters.Add(new ValueParameter<IntValue>("Padding", "The padding inside the boxes", new IntValue(1)));
71      Parameters.Add(new ValueParameter<StringValue>("ZipFileName", "The name of the zip file that will contain all generated charts.", new StringValue("")));
72      Parameters.Add(new ConstrainedValueParameter<StringValue>("AppendMode", "Determines how coordinates of new elements are calculated.",
73        new ItemSet<StringValue>(Enum.GetNames(typeof (AppendModes)).Select(v => new StringValue(v)))));
74      AppendModeParameter.Value = AppendModeParameter.ValidValues.SingleOrDefault(v => v.Value == AppendModes.Horizontal.ToString());
75      RegisterEvents();
76    }
77    public override IDeepCloneable Clone(Cloner cloner) {
78      return new BoxChartCreator(this, cloner);
79    }
80    [StorableHook(HookType.AfterDeserialization)]
81    private void AfterDeserialization() {
82      if (!Parameters.ContainsKey("ZipFileName"))
83        Parameters.Add(new ValueParameter<StringValue>("ZipFileName", "The name of the zip file that will contain all generated charts.", new StringValue("")));
84      if (!Parameters.ContainsKey("AppendMode")) {
85        Parameters.Add(new ConstrainedValueParameter<StringValue>("AppendMode", "Determines how coordinates of new elements are calculated.",
86          new ItemSet<StringValue>(Enum.GetNames(typeof (AppendModes)).Select(v => new StringValue(v)))));
87        AppendModeParameter.Value = AppendModeParameter.ValidValues.SingleOrDefault(v => v.Value == AppendModes.Horizontal.ToString());
88      }
89      RegisterEvents();
90    }
91    #endregion
92
93    private void RegisterEvents() {
94      ElementsParameter.ValueChanged += ElementsParameter_ValueChanged;
95      ElementsParameter.Value.ItemsAdded += ElementsParameter_Value_ItemsAdded;
96    }
97
98    private void ElementsParameter_ValueChanged(object sender, EventArgs e) {
99      ElementsParameter.Value.ItemsAdded += ElementsParameter_Value_ItemsAdded;
100    }
101
102    private void ElementsParameter_Value_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IBoxChartElementGenerator>> e) {
103      if (sender != ElementsParameter.Value) {
104        var oldParameter = sender as ICheckedItemList<IBoxChartElementGenerator>;
105        if (oldParameter != null)
106          oldParameter.ItemsAdded -= ElementsParameter_Value_ItemsAdded;
107      } else {
108        var generators = Generators;
109        var newItems = e.Items.Select(kvp => kvp.Value).ToList();
110        switch (AppendMode) {
111          case AppendModes.Horizontal:
112            foreach (var generator in newItems) {
113              generator.Y = generators.Max(g => g.Y + g.RowSpan - 1);
114              generator.X = generators.Where(g => g.Y + g.RowSpan - 1 == generator.Y).Max(g => g.X + g.ColSpan);
115            }
116            break;
117          case AppendModes.Vertical:
118            foreach (var generator in newItems) {
119              generator.X = generators.Max(g => g.X + g.ColSpan - 1);
120              generator.Y = generators.Where(g => g.X + g.ColSpan - 1 == generator.X).Max(g => g.Y + g.RowSpan);
121            }
122            break;
123        }
124      }
125    }
126
127    #region IRunCollectionModifier Members
128
129    public void Modify(List<IRun> runs) {
130      var bitmaps = new Dictionary<string, Bitmap>();
131      var generators = Generators;
132      var maxX = generators.Max(g => g.X + g.ColSpan);
133      var maxY = generators.Max(g => g.Y + g.RowSpan);
134      for (int i = 0; i<runs.Count; i++) {
135        var run = runs[i];
136        var b = new Bitmap(maxX*Size, maxY*Size);
137        using (var g = Graphics.FromImage(b)) {
138          g.FillRectangle(SystemBrushes.Control, 0, 0, b.Width, b.Height);
139          foreach (var gen in generators) {
140            g.SetClip(new Rectangle(gen.X*Size+Padding, gen.Y*Size+Padding, gen.ColSpan*Size-2*Padding, gen.RowSpan*Size-2*Padding));
141            gen.Draw(run, g);
142            g.ResetClip();
143          }
144        }
145        run.Results[ChartName] = new BitmapItem(b);
146        bitmaps.Add(string.Format("{0}.png", run.Name), (Bitmap)b.Clone());
147      }
148      SaveAllBitmaps(bitmaps);
149    }
150
151    private void SaveAllBitmaps(Dictionary<string, Bitmap> bitmaps) {
152      if (ZipFileNameParameter.Value == null && string.IsNullOrEmpty(ZipFileName))
153        return;
154      var filename = ZipFileName;
155      if (!filename.ToLowerInvariant().EndsWith("zip"))
156        filename = string.Format("{0}.zip", filename);
157      using (var stream = File.Create(filename)) {
158        using (var zipStream = new ZipOutputStream(stream)) {
159          foreach (var bitmap in bitmaps) {
160            zipStream.PutNextEntry(new ZipEntry(bitmap.Key) { DateTime = DateTime.Now });
161            using (var s = new MemoryStream()) {
162              bitmap.Value.Save(s, ImageFormat.Png);
163              zipStream.Write(s.ToArray(), 0, (int)s.Length);
164            }
165          }
166        }
167      }
168    }
169
170    #endregion
171
172  }
173}
Note: See TracBrowser for help on using the repository browser.