After seeing Georg Zoeller’s phenomenal talk on development telemetry at GDC, I had a bunch of ideas about data and interesting things to do with it. I’m still working on my streamlined bug reporting tool for NWN2 (ran into a wall dealing with IPC between C# and C++). This post, however, is about a much flashier, much more finished project.
In the presentation above, there were several screenshots of useful, good-looking visualizations of data, including heatmaps of things like crash locations and gameplay activity. I wanted to be able to make pictures like that! Problem is, I couldn’t find any code or libraries to do quite what I wanted, and rather fighting with what was out there, I decided to roll my own.
I wrote the core code a while ago, so I don’t really remember enough to post-mortem that. Much more recently, though, I felt unsatisfied with the “hacky” (to be generous) interface of one button in a form that ran the whole generation process when you clicked it. It was time to revisit the project.
Most of the interface was just a matter of pulling several parameters to the HeatMap constructor out of code and into the GUI, but it makes me a lot happier to have a tool that other people can reasonably use. At this point, it’s abstract enough to be used for many applications beyond the original use case of plotting deaths on a NWN area minimap.
Besides that, I’m very happy with my approach to scaling the gradient for maximum contrast over the map. The data set mapped in this screenshot, for example, has a massive concentration of points at the gate near the bottom left, and relatively sparse concentrations almost everywhere else. The simplest approach to scaling the gradient is a linear transition from minimum to maximum heat values, but this results in a hot point at the large concentration and cool-looking points over the rest of the map.
I fought with a few different approaches before I realized that I could approach most data sets as being vaguely normal distributions (albeit often skewed left or right). This means percentiles are meaningful, and I can map them to particular points on the color gradient (e.g. dark blue is the 20th percentile, green the 60th, etc.). Rather than some of my dead-end approaches, which required manual tweaking to get a map that looks good, this allows the program to calibrate automatically to the shape of the data set, leaving just a few intuitive parameters to twiddle until the user is satisfied.
In the interest of minimizing the number of times the wheel must be invented, the (C#) code is available here. Do whatever you want with it, though I’d love to hear from you if you find it useful!
(As an aside, WordPress seems to change my C# tag to C++ whenever I save the post. Suppose I’ll do without for now.)