Generating complex math visualizations in SVG using C# and ILNumerics
I was recently turned on to the ILNumerics library. It's a high performance math library for .NET developers that my math skills can barely comprehend. It has a clean and elegant syntax, but more importantly, it's visualization graphics engine is thoughtful, flexible, and well-factored.
Having worked on a lot of websites, including ones that do a lot of backend image generation, resizing and analysis (like check imaging almost 10 years ago) I was impressed at how easily I was able to get an equation onto a basic website with ILNumerics and SVG.
Of course, it's not just a web library, in fact, most of the samples are WPF and WinForms, so it's an engine that you can use anywhere. Regardless, as a web person, I wanted to see how quickly I could get something into my browser.
The ILNumerics website has a cool sample 3D graph on their home page that was generated with this code:
var scene = new ILScene {
new ILPlotCube(twoDMode: false) {
new ILSurface(ILSpecialData.sincf(40, 60, 2.5f)) {
}
}
};
scene.First<ILPlotCube>().Rotation = Matrix4.Rotation(
new Vector3(1f,0.23f,1), 0.7f);
scene;
However, you'll notice in their sample they just end with the variable "scene." That's a no-op there, but it's their coder way of saying "at this point, the scene variable holds a representation of our plot. Do with it as you will."
NOTE: Do check out their home page...the little sample there is deeper than you'd think. The dropdown shows they can generate PNGs, JPGs, JPG HD, SVG, but also "EXE." Hm, download a random EXE from the internet? Yes please! ;) Take a risk and you'll get a nice self-contained EXE visualizer that not only renders the graph but lets you rotate it. You can download the ILView 3D viewer and play around, it's harmless - all the code for ILView is on GitHub! The best part is that it has a built in REPL so you can type your C# right there and see the results! It even runs on Linux and uses Mono. ;)
Back to my goal. I want to use the library on a basic website and dynamically generate an SVG of this plot.
Here's the same plot, put inside an ASP.NET HttpHandler (which could also be made routable and used in ASP.NET MVC/Web Forms, etc.)
public void ProcessRequest(HttpContext context)
{
var scene = new ILScene {
new ILPlotCube(twoDMode: false) {
new ILSurface(ILSpecialData.sincf(40, 60, 2.5f)) {
}
}
};
scene.First<ILPlotCube>().Rotation = Matrix4.Rotation(
new Vector3(1f, 0.23f, 1), 0.7f);
var driver = new ILSVGDriver(context.Response.OutputStream, 1200, 800, scene, Color.White);
driver.Render();
}
Here I'm passing context.Response.OutputStream to their ILSVGDriver and saving the result not to a file, but directly out to the browser. I could certainly save it to cloud blob storage or a local file system for caching, reuse or email.
using (FileStream fs = new FileStream(@"test.svg", FileMode.Create)) {
new ILSVGDriver(fs, scene: whateveryoursceneis).Render();
}
While a SVG is preferable, one could also make a PNG.
var driver = new ILGDIDriver(1280, 800, whateveryoursceneis);
driver.Render();
driver.BackBuffer.Bitmap.Save("whatever", System.Drawing.Imaging.ImageFormat.Png);
Their docs are excellent and many include a similar interactive viewer within the website itself.
It's so much more than a plot visualizer, though. It reminds me a little of D3.js, except more math focused and less live-data binding. It's almost as flexible though, with many kinds of visualizations beyond what you'd expect.
Here's the code to show a green sphere that's composed of triangles, but has the top chopped off, as an example. This is just 10 lines of code, and could be made less.
var scene = new ILScene();
// create a new sphere
var sphere = new ILSphere();
// the sphere is a group containing the Fill (ILTriangles)
// and the Wireframe (ILLines) of the sphere. Both shapes
// share the same vertex positions buffer. Hence, we only
// need to alter one of them:
using (ILScope.Enter()) {
// take the vertex positions from the Fill.Positions buffer
ILArray<float> pos = sphere.Fill.Positions.Storage;
// set all vertices with a Y coordinate larger than 0.3 to 0.3
pos[1, pos[1, ":"] > 0.3f] = 0.3f;
// write all values back to the buffer
sphere.Fill.Positions.Update(pos);
}
// add the "sphere" to the scene
scene.Camera.Add(sphere);
// add another light (for niceness only)
scene.Add(new ILPointLight() {
Position = new Vector3(-0, 1, -2)
});
// move the camera upwards
scene.Camera.Position = new Vector3(0,3,-10);
// display the scene
scene;
And this gives you:
It's a really amazing project. ILNumerics is GPL3 and also uses OpenTK for OpenGL bindings, and Mono.CSharp for C# compiling and evaluation. ILView is under the MIT/X11 license.
You can get it via NuGet with just "Install-Package ILNumerics." Check it out and tell your friends, scientists, and friends of Edward Tufte.
Sponsor: Thanks to Red Gate for sponsoring the feed this week! Check out a simpler way to deploy with Red Gate’s Deployment Manager. It can deploy your .NET apps, services, and databases in a single, repeatable process. Get your free Starter edition now.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
I say that's fair enough. They've clearly put a lot of work in.
But not really for me, I don't make money off the programs I write, I make them to scratch an itch and release them if I think it's going to help others too.
So, NumericalIL is out of the question as I don't have 1k lying around :)
Having said that, I certainly understand the need of getting paid and don't object to that. I guess a gpl version is better than no (unpaid) version at all.
Nice for writing desktop code that want to show off on the web or stuff like this :)
Guess they were concentrating more on the math than the framework guidelines.
var scene = new ILScene {
new ILPlotCube(twoDMode: false) {
new ILSurface(ILSpecialData.sincf(40, 60, 2.5f)) {
}
}
};
I have never seen an object initializer without a named parameter, is this valid C# syntax?
@Will sullivan You name it. The guidelines are great in general. But they sometimes conflict with the need for expressive math syntax.
Regarding the GPL License: We clearly understand the wish for an (even more) free version. There was an LGPL version in the past. But at the end the GPL simply gives us better opportunities for supporting the community in the long run.
But not really for me, I don't make money off the programs I write, I make them to scratch an itch and release them if I think it's going to help others too.
So, NumericalIL is out of the question as I don't have 1k lying around :)
So, why not use the GPL version than? I am positive, your programs will be useful to others, regardless of GPL / LGPL? If one of your users really _needs_ a less restrictive license, you can get in touch with us and we can negotiate a discount on the PRO license.
1. Use object initializer to set properties of the new object:
new ILSurface(ILSpecialData.sincf(40, 60, 2.5f)) {
Wireframe = { Color = Color.Red }
}
2. Use collection initializers to conveniently Add() objects to a new collection. In your example this is used to add the surface to the plot cube and the plot cube to the scene.
var plotcube = scene.Add(new ILPlotCube(...));
plotcube.Add(new ILSurface...);
At this time, the primary reason to invest the effort in learning to use this library vs. the standard open-source graphing tools is when the production environment dictates use of Microsoft technologies.
How many people care about "ILNumerics" on your resume vs. R, ggplot2, etc? Even the python stuff has greater recognition. Every project has to start somewhere though and I'm glad to find out about ILNumerics sooner rather than later.
You are right, there are other graphing tools around. ILNumerics does not so much focus on the prototyping part. It rather eases the "build an application out of it" part. As soon as you must create an application out of your algorithm, build an efficient visualization, have configurable interactivity, pack it into an installer or even deploy it as a single executable to some customers... ILNumerics supports cases like that.
BTW, it is not bound to C#. ILNumerics can be used with every .NET/mono language, let it be C#, F#, VisualBasic or IronPython. And, as Scott pointed out, it runs on Linux without having to recompile :)
But not really for me, I don't make money off the programs I write, I make them to scratch an itch and release them if I think it's going to help others too.
So, NumericalIL is out of the question as I don't have 1k lying around :)
So, why not use the GPL version than? I am positive, your programs will be useful to others, regardless of GPL / LGPL? If one of your users really _needs_ a less restrictive license, you can get in touch with us and we can negotiate a discount on the PRO license.
Because I don't want others to be locked in in GPL, or let them use my code for closed-source or commercial projects. It really depends on the project. GPL is a one way street - almost everything leads in, but nothing out of it.
I appreciate the offer, but like I said, I don't do this for a living or even make a dollar off of it.
Anyway, your library is awesome and keep up the good work :)
asb
Comments are closed.
I don't like how restrictive it is and I wouldn't consider it "free".
Which is a shame, because the library itself looks amazing.