Alex Leach
Alex Leach

Reputation: 1201

How can I efficiently render matrix data as a heatmap in SVG?

I have a matrix of data (96cols by >5000rows), where each value is between -1 and +1. I've written a script to generate a heatmap in SVG format, but the SVG file size with my real datasets becomes massive. Inkscape struggles, with rendering and screen updating really slow. Compressing it to svgz doesn't help either.

I went with the approach of drawing a rect for each value, with each rect having 5 attributes: x, y, width, height and fill. As you can imagine, with 96x5000 values, that's a lot of rects. I reduced the file size from ~34MB to ~29MB by turning each attribute into an integer. The other idea I had was to remove the fill attribute and replace it with one of 10-20 class, one for each colour group. I haven't done that last bit yet though, as I think there must be an even better way of doing it.

As an example:-

    <rect fill="#000000" height="14" width="10" x="50" y="81" />

In HTML, I'd use a <table>, with <tr's> and <th's> with a short class name or id referencing the colour group. If the value is 0, or the middle value, no class name would be needed and the <th> could inherit a preset neutral colour.

With SVG though, apparently there's no formal table specification, so how should I go about this? I'm currently considering the following options:-

  1. The display property does have a (poorly-documented) inline-table option. Apparently though, it could be "an accidental remnant from CSS". I guess this would mean having a <g> for each row, with an id referencing a style with display:table-row-group.
  2. Use <text> elements as rows, with nested <tspan>s, as suggested here.
  3. Use a layout manager written in ECMASCript.

I've also briefly checked out XSLT, which looks powerful, but complicated, and also seems like it would only work in a web browser. I'd ideally like to keep everything in a single file that can be saved, viewed and edited in a vector graphics editor, and am not sure if XSLT allows for this.

What would be the most efficient way of doing this? Filesize isn't so important as the speed at which it renders. Any help much appreciated.

UPDATE:-

I also wondered whether line length might have something to do with the slow rendering.. I'm using Python's (c)ElementTree module to generate the SVG, and by default it writes all XML without a single new-line character. Might it help parsers / renderers to separate each of the image's rows into a new line in the XML?

Upvotes: 0

Views: 2492

Answers (1)

Robert Longson
Robert Longson

Reputation: 123985

I suspect you may be better off using canvas for this. Create a canvas and then draw rectangles on the canvas. The rectangles will only exist as part of the canvas bitmap.

Upvotes: 2

Related Questions