Skip to content

Repository files navigation

ProEssentials WinUI Realtime Heatmap — Spectrogram — 2D Contour

A ProEssentials v11 WinUI 3 .NET 10 demonstration of a realtime heatmap / spectrogram / 2D contour chart that replaces the entire 93,696-value surface every 25ms using a tiled data pool with per-row horizontal shifting — the full frequency landscape scrolls left/right like a live spectrum analyzer without any vertical drift.

Looking for the simpler non-realtime version? See winui-heatmap-2d-contour-spectrogram-frequency-proessentials — same chart configuration, no timer, ideal as a starting point.

ProEssentials Realtime Heatmap


What Makes This Different

Most realtime chart examples scroll data in one direction like a strip chart. This example replaces the entire heatmap surface simultaneously each tick — every frequency band shifts horizontally in unison, like a live spectrum analyzer or SDR waterfall display.

The chart-configuration code is identical to the WPF and WinForms versions of this example. The ProEssentials API does not change between interfaces; only the window plumbing differs.


Architecture

fZDataPool[281,088]  ← Heatmap.txt Z values tiled 3× in memory
                        3 × 93,696 = 281,088 floats (~1.1 MB)

fZDataToChart[93,696]← Fixed buffer — UseDataAtLocation points here permanently.
                        Per-row Array.Copy writes shifted data each tick.
                        Chart reads from the same fixed address every frame.
                        At ~366KB, safely above the 85KB GC pinning threshold.

fXDataPool[512]      ← X axis values — FastCopyFrom at init (512 floats = 2KB,
                        under 85KB threshold, unsafe for UseDataAtLocation)
fYDataPool[183]      ← Y axis values — FastCopyFrom at init (183 floats = ~720B,
                        under 85KB threshold, unsafe for UseDataAtLocation)

85KB pinning rule: Arrays under ~85KB can be relocated by the .NET GC. UseDataAtLocation stores a raw pointer — if the GC moves a small array, the pointer becomes invalid and the chart reads garbage data or crashes. Arrays above 85KB go on the Large Object Heap and are never relocated. Always use FastCopyFrom for small arrays, UseDataAtLocation only for large ones.

Init:

// X and Y: FastCopyFrom — safely copies small arrays into ProEssentials' own buffer
Pesgo1.PeData.X.FastCopyFrom(fXDataPool, POINTS);
Pesgo1.PeData.Y.FastCopyFrom(fYDataPool, SUBSETS);

// Z: UseDataAtLocation — ~366KB, safe on Large Object Heap, pointer never relocates
Pesgo1.PeData.Z.UseDataAtLocation(fZDataToChart, FRAME_SIZE);

Each tick — per-row horizontal shift with wrap:

m_nZOffset += Rand_Num.Next(50, 200);
if (m_nZOffset >= POINTS) { m_nZOffset = 0; }

int rightLen = POINTS - m_nZOffset;
for (int s = 0; s < SUBSETS; s++)
{
    int srcRow = s * POINTS;
    int dstRow = s * POINTS;
    // Right portion — from colOffset to end of row
    Array.Copy(fZDataPool, srcRow + m_nZOffset, fZDataToChart, dstRow,            rightLen);
    // Left portion — wrap from start of row
    Array.Copy(fZDataPool, srcRow,              fZDataToChart, dstRow + rightLen, m_nZOffset);
}

Pesgo1.PeData.ReuseDataX = true;  // prevent unnecessary CPU→GPU X transfer
Pesgo1.PeData.ReuseDataY = true;  // prevent unnecessary CPU→GPU Y transfer
Pesgo1.PeFunction.Force3dxNewColors      = true;
Pesgo1.PeFunction.Force3dxVerticeRebuild = true;
Pesgo1.Invalidate();

Each row stays in its correct Y frequency band — only the X position within each row advances, giving pure horizontal movement.


Step Size Tuning

m_nZOffset += Rand_Num.Next(50, 200);  // ← tune this
Step Range Effect
Next(1, 10) Slow, smooth horizontal drift
Next(50, 200) Natural organic movement ← default
Next(500, 2000) Dramatic rapid shifting

ProEssentials Features Demonstrated

UseDataAtLocation(array, count) — passes a direct pointer to a large fixed buffer. The chart reads from that address every frame without any internal copy. Only safe for arrays ≥ 85KB (Large Object Heap).

FastCopyFrom(array, count) — copies small arrays into ProEssentials' own internal buffer. Safe for any size — required for X and Y arrays that are under the 85KB GC relocation threshold.

ReuseDataX / ReuseDataY — signals that X and Y are unchanged since the last tick. Prevents ProEssentials from re-transferring these arrays CPU→GPU every frame — important for performance even when not using staging buffers.

ComputeShader — GPU handles contour color interpolation for all 93,696 Z values every tick. No staging buffers needed for 2D contour — only the 3D line/scatter path requires them.

DuplicateDataX / DuplicateDataY — only 512 X values and 183 Y values stored; chart duplicates them across all subsets/points.

Composite2D3D.Foreground — Direct3D renders the contour fill, 2D axis/grid/labels composited on top in the foreground.

ContourColors — interpolated color fill between contour lines. Blue (low Z) → Cyan → Green → Yellow → Brown → White (high Z).

Log Y axis — equal visual space per octave, standard for frequency data.

Cursor prompt disabled in realtime mode — PromptTracking triggers hit testing on every mouse move event which stalls the timer loop in realtime mode. Commented out with a note — re-enable for static use.


Data File

Heatmap.txt — 93,696 lines, tab-delimited X/Y/Z. 183 rows × 512 columns. Copied to output directory on build.


Prerequisites

  • Visual Studio 2026 with the .NET desktop development and Windows application development workloads
  • .NET 10 SDK
  • Dedicated GPU recommended
  • Internet connection for NuGet restore

How to Run

1. Clone this repository
2. Open RealtimeHeatmapWinUI.sln in Visual Studio 2026
3. Build → Rebuild Solution (NuGet restore is automatic)
4. Press F5

NuGet Package

References ProEssentials.Chart.Net10.WinUI. Restore is automatic on build.

The AnyCpu package embeds the native rendering engines inside the assembly and unpacks the one matching the running process at run time, so there is no native DLL to copy or deploy alongside your app.


No XAML Designer

Visual Studio has no XAML designer for WinUI 3 — not in any edition, including Visual Studio 2026. The Toolbox is empty for WinUI projects by design, so the chart is declared in markup (<pe:PesgoWinUI x:Name="Pesgo1" Loaded="Pesgo1_Loaded" />) rather than dragged onto a design surface. This is a Windows App SDK limitation that applies to every WinUI control vendor, not a ProEssentials one.

The other WinUI window differences worth knowing, all visible in this sample:

  • A WinUI Window is not a Control. It has no Height/Width/ MinHeight/MinWidth in XAML — SizeAndCenterWindow() sets the size with a Win32 MoveWindow call.
  • WPF's cancellable Closing becomes WinUI's Closed, which is where the 25ms timer is stopped.
  • WPF's DispatcherTimer becomes a DispatcherQueueTimer created from the window's own DispatcherQueue.
  • WinUI 3 has no MessageBox, so the missing-data-file notice calls the Win32 MessageBoxW directly.

Deploying a WinUI App

WinUI deploys differently than WPF and WinForms — worth knowing before you ship:

  • A .NET app is not a single exe. Ship the entire build/publish output folder, never a hand-picked subset. Heatmap.txt is part of that folder.
  • The target machine needs two runtimes: the .NET 10 Desktop Runtime and the Windows App SDK Runtime. Alternatively publish self-contained with -p:WindowsAppSDKSelfContained=true.
  • Your development machine already has both, so it will run from an under-filled folder. Always validate on a clean machine.

Evaluation Watermark

The nuget.org package is the evaluation build and draws an "Evaluating ProEssentials" watermark across the chart. A licensed installation replaces the assembly and the watermark goes away — everything else behaves identically.


Related Examples


License

Example code is MIT licensed. ProEssentials requires a commercial license for continued use.

About

WinUI 3 realtime spectrogram analyzer, .NET 10 C# - the full 93K surface replaced every 25ms by a per-row horizontal shift. Zero-copy UseDataAtLocation Z buffer, FastCopyFrom X/Y, ReuseDataX/Y, GPU compute shader. PesgoWinUI, Direct3D.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages