@@ -37,6 +37,12 @@ public sealed class SampleMonitor : ISampleMonitor {
37
37
/// </summary>
38
38
public bool Collect { get ; }
39
39
40
+ /// <summary>
41
+ /// The name of the variable that is being monitored.
42
+ /// Used for output in <see cref="Summarize(bool, int, double?, double?)"/>.
43
+ /// </summary>
44
+ public string Name { get ; set ; }
45
+
40
46
public int Count { get ; private set ; }
41
47
42
48
public double Min { get ; private set ; }
@@ -97,7 +103,8 @@ private static double GetPercentile(IList<double> s, double p) {
97
103
return s . OrderBy ( x => x ) . Skip ( k - 1 ) . Take ( 2 ) . Average ( ) ;
98
104
}
99
105
100
- public SampleMonitor ( bool collect = false ) {
106
+ public SampleMonitor ( string name = null , bool collect = false ) {
107
+ Name = name ;
101
108
Collect = collect ;
102
109
if ( collect ) samples = new List < double > ( 64 ) ;
103
110
}
@@ -137,16 +144,45 @@ private void OnUpdated() {
137
144
Updated ? . Invoke ( this , EventArgs . Empty ) ;
138
145
}
139
146
140
- public string Print ( string name = null , double ? histMin = null , double ? histInterval = null ) {
147
+ string IMonitor . Summarize ( ) {
148
+ return Summarize ( ) ;
149
+ }
150
+
151
+ /// <summary>
152
+ /// Provides a summary of the statistics in a certain format.
153
+ /// If the monitor is configured to collect data, it may also print a histogram.
154
+ /// </summary>
155
+ /// <param name="withHistogram">Whether to suppress the histogram.
156
+ /// This is only effective if <see cref="Collect"/> was set to true, otherwise
157
+ /// the data to produce the histogram is not available in the first place.</param>
158
+ /// <param name="maxBins">The maximum number of bins that should be used.
159
+ /// Note that the bin width and thus the number of bins is also governed by
160
+ /// <paramref name="histInterval"/> if it is defined.
161
+ /// This is only effective if <see cref="Collect"/> and <paramref name="withHistogram"/>
162
+ /// was set to true, otherwise the data to produce the histogram is not available
163
+ /// in the first place.</param>
164
+ /// <param name="histMin">The minimum for the histogram to start at or the sample
165
+ /// minimum in case the default (null) is given.
166
+ /// This is only effective if <see cref="Collect"/> and <paramref name="withHistogram"/>
167
+ /// was set to true, otherwise the data to produce the histogram is not available
168
+ /// in the first place.</param>
169
+ /// <param name="histInterval">The interval for the bins of the histogram or the
170
+ /// range (<see cref="Max"/> - <see cref="Min"/>) divided by the number of bins
171
+ /// (<paramref name="maxBins"/>) in case the default value (null) is given.
172
+ /// This is only effective if <see cref="Collect"/> and <paramref name="withHistogram"/>
173
+ /// was set to true, otherwise the data to produce the histogram is not available
174
+ /// in the first place.</param>
175
+ /// <returns>A formatted string that provides a summary of the statistics.</returns>
176
+ public string Summarize ( bool withHistogram = true , int maxBins = 20 , double ? histMin = null , double ? histInterval = null ) {
141
177
var nozero = Collect ? samples . Where ( x => x != 0 ) . ToList ( ) : new List < double > ( ) ;
142
178
var nozeromin = nozero . Count > 0 ? nozero . Min ( ) : double . NaN ;
143
179
var nozeromax = nozero . Count > 0 ? nozero . Max ( ) : double . NaN ;
144
180
var nozeromean = nozero . Count > 1 ? nozero . Average ( ) : double . NaN ;
145
181
var nozerostdev = nozero . Count > 2 ? Math . Sqrt ( nozero . Sum ( x => ( x - nozeromean ) * ( x - nozeromean ) ) / ( nozero . Count - 1.0 ) ) : double . NaN ;
146
182
var sb = new StringBuilder ( ) ;
147
183
sb . Append ( "Statistics" ) ;
148
- if ( ! string . IsNullOrEmpty ( name ) )
149
- sb . Append ( " of " + name ) ;
184
+ if ( ! string . IsNullOrEmpty ( Name ) )
185
+ sb . Append ( " of " + Name ) ;
150
186
sb . AppendLine ( ) ;
151
187
sb . AppendLine ( " all excl.zero zero " ) ;
152
188
sb . AppendLine ( "--------------- --------------- --------------- ---------------" ) ;
@@ -162,19 +198,20 @@ public string Print(string name = null, double? histMin = null, double? histInte
162
198
}
163
199
sb . AppendLine ( string . Format ( "{0,15} {1,15} {2,15}" , "Maximum" , Formatter . Format15 ( Max ) , Formatter . Format15 ( nozeromax ) ) ) ;
164
200
165
- if ( Collect ) {
201
+ if ( Collect && withHistogram ) {
166
202
var min = histMin ?? Min ;
167
- var interval = histInterval ?? ( Max - Min ) / 20.0 ;
168
- var histData = samples . GroupBy ( x => ( int ) Math . Floor ( Math . Max ( x - min + interval , 0 ) / interval ) )
169
- . ToDictionary ( x => x . Key , x => x . Count ( ) ) ;
203
+ var interval = histInterval ?? ( Max - Min ) / maxBins ;
204
+ var histData = samples . GroupBy ( x => x <= min ? 0 : ( int ) Math . Floor ( Math . Min ( ( x - min + interval ) / interval , maxBins ) ) )
205
+ . Select ( x => new { Key = x . Key , Value = x . Count ( ) } )
206
+ . OrderBy ( x => x . Key ) ;
170
207
sb . AppendLine ( ) ;
171
208
sb . AppendLine ( "Histogram" ) ;
172
209
sb . AppendLine ( "<= count % cum% " ) ;
173
210
sb . AppendLine ( "--------------- ---------- ----- ------" ) ;
174
211
var cumul = 0.0 ;
175
212
var totStars = 0 ;
176
213
var last = - 1 ;
177
- foreach ( var kvp in histData . OrderBy ( x => x . Key ) ) {
214
+ foreach ( var kvp in histData ) {
178
215
while ( kvp . Key > last + 1 ) {
179
216
last ++ ;
180
217
var tmp = "|" . PadLeft ( totStars + 1 ) ;
@@ -189,7 +226,9 @@ public string Print(string name = null, double? histMin = null, double? histInte
189
226
var stars = string . Join ( "" , Enumerable . Repeat ( "*" , numstars ) ) ;
190
227
totStars += numstars ;
191
228
var cumulbar = "|" . PadLeft ( totStars + 1 - numstars ) ;
192
- sb . AppendLine ( string . Format ( "{0,15} {1,10} {2,5:F1} {3,5:F1} {4}{5}" , Formatter . Format15 ( min + kvp . Key * interval ) , kvp . Value , prob * 100 , cumul * 100 , stars , cumulbar ) ) ;
229
+ sb . AppendLine ( string . Format ( "{0,15} {1,10} {2,5:F1} {3,5:F1} {4}{5}" ,
230
+ ( kvp . Key == maxBins && min + kvp . Key * interval < Max ) ? "inf" : Formatter . Format15 ( min + kvp . Key * interval ) ,
231
+ kvp . Value , prob * 100 , cumul * 100 , stars , cumulbar ) ) ;
193
232
last = kvp . Key ;
194
233
}
195
234
}
0 commit comments