NTP Analyzer  0.8.2
Analyze the operation of time servers
GraphBase.cs
Go to the documentation of this file.
1 //
2 // Copyright (c) 2013-2017 Carsten Sonne Larsen <cs@innolan.net>
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 
22 using System;
23 using System.Collections;
24 using System.Collections.Generic;
25 using System.Drawing;
26 using System.Drawing.Drawing2D;
27 using System.Drawing.Imaging;
28 using System.IO;
29 using NPlot;
30 using Ntp.Analyzer.Export;
31 using Ntp.Analyzer.Interface;
32 using PlotSurface2D = NPlot.Bitmap.PlotSurface2D;
33 
34 namespace Ntp.Analyzer.Graph
35 {
36  public abstract class GraphBase : IStreamGenerator
37  {
38  protected GraphBase(IGraphBaseConfiguration baseConfig)
39  {
40  this.baseConfig = baseConfig;
41  destinations = new List<StreamDestination>(baseConfig.Locations);
42  }
43 
44  private static readonly object Locker = new object();
46  private readonly List<StreamDestination> destinations;
47 
48  protected abstract string YLabel { get; }
49 
50  protected PlotSurface2D Surface { get; private set; }
51 
52  protected TimeSpan GraphTimeSpan => new TimeSpan(baseConfig.Timespan, 0, 0, 0);
53 
54  public string ImageFileExtension => "png";
55 
56  public IEnumerable<StreamDestination> Destinations => destinations;
57 
58  public Stream Generate()
59  {
60  Surface = new PlotSurface2D(baseConfig.Width, baseConfig.Height);
61 
62  // Only one loader at the time
63  lock (Locker)
64  {
65  LoadData();
66  }
67 
68  var titleFont = new Font("Arial", 12);
69  var axisFont = new Font("Arial", 10);
70  var legendFont = new Font("Arial", 10);
71  var tickFont = new Font("Arial", 8);
72 
73  // Prepare PlotSurface:
74  Surface.Clear();
75  Surface.Title = baseConfig.Title;
76  Surface.TitleFont = titleFont;
77  Surface.SmoothingMode = SmoothingMode.HighQuality;
78  Surface.BackColor = Color.White;
79  Surface.Add(new Grid(), NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Left);
80 
81  AddPlots();
82 
83  // Prepare axis
84  Surface.XAxis1.Label = string.Empty;
85  Surface.XAxis1.LabelFont = axisFont;
86  Surface.XAxis1.TickTextFont = tickFont;
87  Surface.XAxis1.TicksLabelAngle = 0;
88  Surface.XAxis1.TickTextNextToAxis = true;
89  Surface.XAxis1.FlipTicksLabel = true;
90  Surface.XAxis1.LabelOffset = 95;
91  Surface.XAxis1.LabelOffsetAbsolute = true;
92  Surface.XAxis1.NumberFormat = baseConfig.Timespan <= 2 ? "HH" : "MMMM d";
93  Surface.YAxis1.Label = YLabel;
94  Surface.YAxis1.LabelFont = axisFont;
95  Surface.YAxis1.LabelOffsetScaled = true;
96  Surface.YAxis1.TickTextFont = tickFont;
97  Surface.YAxis1.NumberFormat = "{0:####0.00}";
98 
99  if (Surface.YAxis2 != null)
100  {
101  Surface.YAxis2.Label = "Value";
102  Surface.YAxis2.LabelFont = axisFont;
103  Surface.YAxis2.TickTextFont = tickFont;
104  Surface.YAxis2.NumberFormat = "{0:####0.00}";
105  }
106 
107  // Add legend
108  var legend = new Legend {Font = legendFont};
109  legend.AttachTo(NPlot.PlotSurface2D.XAxisPosition.Top, NPlot.PlotSurface2D.YAxisPosition.Left);
110  legend.VerticalEdgePlacement = Legend.Placement.Inside;
111  legend.HorizontalEdgePlacement = Legend.Placement.Inside;
112  legend.BorderStyle = LegendBase.BorderType.Line;
113  legend.BackgroundColor = Color.White;
114  legend.XOffset = 20;
115  legend.YOffset = 15;
116  Surface.Legend = legend;
117  Surface.LegendZOrder = 10;
118 
119  PreRender();
120 
121  return Render();
122  }
123 
124  public Stream Render()
125  {
126  var stream = new MemoryStream();
127 
128  if (Surface == null)
129  return stream;
130 
131  // Only one rendering at the time
132  lock (Locker)
133  {
134  using (var b = new Bitmap(baseConfig.Width, baseConfig.Height))
135  using (var g = Graphics.FromImage(b))
136  {
137  g.FillRectangle(new Pen(Color.White).Brush, 0, 0, b.Width, b.Height);
138  Surface.Draw(Graphics.FromImage(b), new Rectangle(0, 0, b.Width, b.Height));
139 
140  b.Save(stream, ImageFormat.Png);
141  }
142 
143  // Force garbage collection
144  GC.Collect();
145  }
146 
147  return stream;
148  }
149 
150  protected abstract void AddPlots();
151 
152  protected abstract void LoadData();
153 
154  protected virtual void PreRender()
155  {
156  }
157 
158  protected LinePlot SetupPlot(string name, Color color, IList time, IList data)
159  {
160  var plot = new LinePlot
161  {
162  AbscissaData = time,
163  DataSource = data,
164  Color = color,
165  Shadow = false,
166  Label = name
167  };
168 
169  return plot;
170  }
171  }
172 }
NPlot.Bitmap.PlotSurface2D PlotSurface2D
Definition: GraphBase.cs:32
GraphBase(IGraphBaseConfiguration baseConfig)
Definition: GraphBase.cs:38
readonly List< StreamDestination > destinations
Definition: GraphBase.cs:46
virtual void PreRender()
Definition: GraphBase.cs:154
LinePlot SetupPlot(string name, Color color, IList time, IList data)
Definition: GraphBase.cs:158
var b
Definition: bootstrap.min.js:6
readonly IGraphBaseConfiguration baseConfig
Definition: GraphBase.cs:45