This repository has been archived on 2024-06-04. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
thesis-src/Examples/ReportGenerator/Table/ReportGenerator.cs
Simon Gruber ea51f37f81 Checkpoint
2023-11-22 06:37:00 +01:00

172 lines
4.5 KiB
C#

using Common.Extensions;
using ReportGenerator.Models;
using System.Text;
namespace ReportGenerator.Table
{
public class ReportGenerator
{
private ICollection<ImageStats> Images { get; }
private readonly StringBuilder _sb = new();
private ReportGenerator(IEnumerable<ImageStats> stats) => Images = stats.ToArray();
/// <inheritdoc />
public override string ToString() => _sb.ToString();
#region Fluent definition
public ReportGenerator WithTitle(string text)
{
_sb.AppendHeading(1, text);
return this;
}
public ReportGenerator WithFullStatistic(string title)
{
_sb.AppendHeading(2, title);
foreach (var stat in Images)
{
_sb.AppendHeading(3, stat.ImageName);
_sb.AppendParagraph(HtmlImage(Path.Combine("img", stat.ImageName), 350, 350));
AppendRow(stat
.Reference
.Prepend("Image")
.Prepend("CER (avg)")
.Prepend("WER")
.Prepend("Elapsed")
.Prepend("Processor")
);
AppendRowSeparator(stat.Reference.Count + 5);
var processors = stat.Processors
.OrderBy(s => s.Distance)
.ThenBy(s => s.ProcessingTime);
foreach (var processor in processors)
{
var imgPath = Path.Combine("results", $"{processor.Name}.00.{stat.ImageName}.png");
AppendRow(processor.Words
.Select(s => s.ToString() ?? string.Empty)
.Prepend(HtmlImage(imgPath, 150, 150))
.Prepend(processor.Words.Average(s => s.Distance).ToString("F2"))
.Prepend($"{processor.Distance * 100:F1}%")
.Prepend($"{processor.ProcessingTime * 1000:F1}ms")
.Prepend(processor.Name)
);
}
_sb.AppendLine();
_sb.AppendParagraph(
$"*Comparison data generated based on {stat.Reference.Count} tagged words.*"
);
}
return this;
}
public ReportGenerator WithBestOf(string title, int context = 5)
{
_sb.AppendHeading(2, title);
var lookup = Images
.SelectMany(s => s.Processors)
.ToLookup(p => p.Name);
// Compare time across all images
var byTime = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.ProcessingTime) * 1000))
.OrderBy(g => g.Value);
// Compare WER across all images
var byWer = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.Distance) * 100))
.OrderBy(g => g.Value);
// Compare CER across all images
var byCer = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.Words.Average(w => w.Distance))))
.OrderBy(g => g.Value);
// Print
AppendComparison(3, "Time", byTime, " ms");
AppendComparison(3, "WER", byWer, " %");
AppendComparison(3, "CER", byCer, " changes");
return this;
void AppendComparison(
int level,
string tableTitle,
IEnumerable<(string, double)> values,
string valueUnit = ""
)
{
var tValues = values.ToArray();
var tContext = Math.Min(tValues.Length / 2, context);
_sb.AppendHeading(level, tableTitle);
AppendRow(new[] { "Processor", "Average" });
AppendRowSeparator(2);
AppendRows(tValues.Take(tContext).Select(v => new[]
{
v.Item1,
v.Item2.ToString("F2") + valueUnit
}));
AppendRowSeparator(2, "...");
AppendRows(tValues.TakeLast(tContext).Select(v => new[]
{
v.Item1,
v.Item2.ToString("F2") + valueUnit
}));
}
}
#endregion
#region Helpers
private void AppendRow(IEnumerable<string> row)
{
const string separator = " | ";
_sb.AppendLine(separator + string.Join(" | ", row) + separator);
}
private void AppendRows(IEnumerable<IEnumerable<string>> rows)
{
foreach (var row in rows)
{
AppendRow(row);
}
}
private static string HtmlImage(string path, int maxWidth, int maxHeight)
{
if (!path.EndsWith(".png"))
{
path += ".png";
}
return $"<img src=\"{path}\" style=\"max-width:{maxWidth}px;max-height:{maxHeight}px;\" />";
}
private void AppendRowSeparator(int columns, string content = "---") =>
AppendRow(Enumerable.Range(0, columns).Select(_ => content));
#endregion
#region Factory Methods
public static ReportGenerator FromData(IEnumerable<ImageStats> stats) => new(stats);
#endregion
}
}