Skip to content

Commit

Permalink
Add violin plots for reliability
Browse files Browse the repository at this point in the history
And move custom imraii stuff to imraii2
  • Loading branch information
WorkingRobot committed Nov 13, 2023
1 parent f63483c commit bdce750
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 94 deletions.
1 change: 1 addition & 0 deletions Craftimizer/Craftimizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

<ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.12" />
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
<PackageReference Include="Meziantou.Analyzer" Version="2.0.106">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
2 changes: 1 addition & 1 deletion Craftimizer/ImGuiExtras.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Runtime.InteropServices;
using System.Text;

namespace Craftimizer;
namespace Craftimizer.Plugin;

internal static unsafe class ImGuiExtras
{
Expand Down
102 changes: 71 additions & 31 deletions Craftimizer/ImGuiUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii;
using ImGuiNET;
using ImPlotNET;
using MathNet.Numerics.Statistics;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -130,44 +134,14 @@ public static void EndGroupPanel()
ImGui.PopID();
}

private struct EndUnconditionally : ImRaii.IEndObject, IDisposable
{
private Action EndAction { get; }

public bool Success { get; }

public bool Disposed { get; private set; }

public EndUnconditionally(Action endAction, bool success)
{
EndAction = endAction;
Success = success;
Disposed = false;
}

public void Dispose()
{
if (!Disposed)
{
EndAction();
Disposed = true;
}
}
}

public static ImRaii.IEndObject GroupPanel(string name, float width, out float internalWidth)
{
internalWidth = BeginGroupPanel(name, width);
return new EndUnconditionally(EndGroupPanel, true);
}

private static Vector2 UnitCircle(float theta)
{
var (s, c) = MathF.SinCos(theta);
// SinCos positive y is downwards, but we want it upwards for ImGui
return new Vector2(c, -s);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float Lerp(float a, float b, float t) =>
MathF.FusedMultiplyAdd(b - a, t, a);

Expand Down Expand Up @@ -251,6 +225,72 @@ public static void ArcProgress(float value, float radiusInner, float radiusOuter
Arc(MathF.PI / 2, MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1), radiusInner, radiusOuter, backgroundColor, filledColor);
}

public sealed class ViolinData
{
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public float X, Y, Y2;

public Point(float x, float y, float y2)
{
X = x;
Y = y;
Y2 = y2;
}
}

public ReadOnlySpan<Point> Data => (DataArray ?? Array.Empty<Point>()).AsSpan();
private Point[]? DataArray { get; set; }
public readonly float Min;
public readonly float Max;

public ViolinData(IEnumerable<int> samples, float min, float max, int resolution, double bandwidth)
{
Min = min;
Max = max;
bandwidth *= Max - Min;
var samplesList = samples.AsParallel().Select(s => (double)s).ToArray();
_ = Task.Run(() => {
var s = Stopwatch.StartNew();
var data = ParallelEnumerable.Range(0, resolution)
.Select(n => Lerp(min, max, n / (float)resolution))
.Select(n => (n, (float)KernelDensity.EstimateGaussian(n, bandwidth, samplesList)))
.Select(n => new Point(n.n, n.Item2, -n.Item2));
DataArray = data.ToArray();
s.Stop();
Log.Debug($"Violin plot processing took {s.Elapsed.TotalMilliseconds:0.00}ms");
});
}
}

public static void ViolinPlot(in ViolinData data, Vector2 size)
{
using var padding = ImRaii2.PushStyle(ImPlotStyleVar.PlotPadding, Vector2.Zero);
using var plotBg = ImRaii2.PushColor(ImPlotCol.PlotBg, Vector4.Zero);
using var frameBg = ImRaii2.PushColor(ImPlotCol.FrameBg, Vector4.Zero);
using var fill = ImRaii2.PushColor(ImPlotCol.Fill, Vector4.One.WithAlpha(.5f));

using var plot = ImRaii2.Plot("##violin", size, ImPlotFlags.CanvasOnly);
if (plot)
{
ImPlot.SetupAxes(null, null, ImPlotAxisFlags.NoDecorations, ImPlotAxisFlags.NoDecorations | ImPlotAxisFlags.AutoFit);
ImPlot.SetupAxisLimits(ImAxis.X1, data.Min, data.Max, ImPlotCond.Always);
ImPlot.SetupFinish();

if (data.Data is { } points && !points.IsEmpty)
{
unsafe {
var label_id = stackalloc byte[] { (byte)'\0' };
fixed (ViolinData.Point* p = points)
{
ImPlotNative.ImPlot_PlotShaded_FloatPtrFloatPtrFloatPtr(label_id, &p->X, &p->Y, &p->Y2, points.Length, ImPlotShadedFlags.None, 0, sizeof(ViolinData.Point));
}
}
}
}
}

private sealed class SearchableComboData<T> where T : class
{
public readonly ImmutableArray<T> items;
Expand Down
92 changes: 92 additions & 0 deletions Craftimizer/ImRaii2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Dalamud.Interface.Utility.Raii;
using ImPlotNET;
using System;
using System.Numerics;

namespace Craftimizer.Plugin;

public static class ImRaii2
{
private struct EndUnconditionally : ImRaii.IEndObject, IDisposable
{
private Action EndAction { get; }

public bool Success { get; }

public bool Disposed { get; private set; }

public EndUnconditionally(Action endAction, bool success)
{
EndAction = endAction;
Success = success;
Disposed = false;
}

public void Dispose()
{
if (!Disposed)
{
EndAction();
Disposed = true;
}
}
}

private struct EndConditionally : ImRaii.IEndObject, IDisposable
{
public bool Success { get; }

public bool Disposed { get; private set; }

private Action EndAction { get; }

public EndConditionally(Action endAction, bool success)
{
EndAction = endAction;
Success = success;
Disposed = false;
}

public void Dispose()
{
if (!Disposed)
{
if (Success)
{
EndAction();
}

Disposed = true;
}
}
}

public static ImRaii.IEndObject GroupPanel(string name, float width, out float internalWidth)
{
internalWidth = ImGuiUtils.BeginGroupPanel(name, width);
return new EndUnconditionally(ImGuiUtils.EndGroupPanel, true);
}

public static ImRaii.IEndObject Plot(string title_id, Vector2 size, ImPlotFlags flags)
{
return new EndConditionally(new Action(ImPlot.EndPlot), ImPlot.BeginPlot(title_id, size, flags));
}

public static ImRaii.IEndObject PushStyle(ImPlotStyleVar idx, Vector2 val)
{
ImPlot.PushStyleVar(idx, val);
return new EndUnconditionally(ImPlot.PopStyleVar, true);
}

public static ImRaii.IEndObject PushStyle(ImPlotStyleVar idx, float val)
{
ImPlot.PushStyleVar(idx, val);
return new EndUnconditionally(ImPlot.PopStyleVar, true);
}

public static ImRaii.IEndObject PushColor(ImPlotCol idx, Vector4 col)
{
ImPlot.PushStyleColor(idx, col);
return new EndUnconditionally(ImPlot.PopStyleColor, true);
}
}
2 changes: 1 addition & 1 deletion Craftimizer/Windows/MacroClipboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public override void Draw()
private void DrawMacro(int idx, string macro)
{
using var id = ImRaii.PushId(idx);
using var panel = ImGuiUtils.GroupPanel($"Macro {idx + 1}", -1, out var availWidth);
using var panel = ImRaii2.GroupPanel($"Macro {idx + 1}", -1, out var availWidth);

var cursor = ImGui.GetCursorPos();

Expand Down
Loading

1 comment on commit bdce750

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: bdce750 Previous: 4bf7397 Ratio
Craftimizer.Benchmark.Bench.Solve(State: 5372D31C98FA4C357F54029912394B0F5ECBE94AEC9D12C1C2B7F453C62ACD2F, Config: E1C895829E5BB1533C41D3C71AD65B6B3E1A60B5EE2D35A845744C251E71EFA5) 1411110208.3333333 ns (± 7090465.712036171)
Craftimizer.Benchmark.Bench.Solve(State: 5372D31C98FA4C357F54029912394B0F5ECBE94AEC9D12C1C2B7F453C62ACD2F, Config: E1C895829E5BB1533C41D3C71AD65B6B3E1A60B5EE2D35A845744C251E71EFA5) 1101126650 ns (± 1836911.863280745)
Craftimizer.Benchmark.Bench.Solve(State: 99B0F1AD46A18B4D8262F9BA75ABE23507217C2F20FBF895A49282DDFEF50190, Config: E1C895829E5BB1533C41D3C71AD65B6B3E1A60B5EE2D35A845744C251E71EFA5) 1544205466.6666667 ns (± 2966406.1179593513)
Craftimizer.Benchmark.Bench.Solve(State: 99B0F1AD46A18B4D8262F9BA75ABE23507217C2F20FBF895A49282DDFEF50190, Config: E1C895829E5BB1533C41D3C71AD65B6B3E1A60B5EE2D35A845744C251E71EFA5) 1163688150 ns (± 2900770.571563038)

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.