Sunday, January 13, 2013

High Resolution NOAA SST with WebGL

This is another in the series of experiments with dynamic global presentations with WebGL. It is SST anomaly data (AVHRR) from 21 December 2012. In fact, NOAA High Resolution SST data provided by the NOAA/OAR/ESRL PSD, Boulder, Colorado, USA, from their Web site at This experiment is more about data handling than science; the million points of a 1/4 deg grid (about 25kmn resolution) are challenging. So is the task of actually getting it on your screen; Firefox works for me, but not IE and it's patchy in Chrome. Sometimes restarting the browser makes the difference. It takes a few seconds to show, so I've put it below the jump.

The plot is of anomalies. NOAA also gives the actual temperatures, but their plot is less informative. Most of the range of colors is used in just expressing the equator to pole variation, so you learn little about what is different currently.

As elsewhere, you can rotate the globe as a trackball, or zoom by dragging the right button vertically. I'll discuss some of the data issues below the plot.

The picture

The scale on the right shows the anomaly units in °C. They can be quite large. There appears to be a La Nina jet in mid-Pacific. The North Atlantic variations are considerable, as is the N Pacific cold spot. Note the persistence of warmth north of Norway, where the ice is low for winter.

Download minimising

There are about a million data points. The grid is regular, so no need to send latitude or longitude, and with 256 colors, the base load is a Mb - significant for a web page download.

However, Javascript does not send floating point, so the naive method is comma-separated text, 4-5 bytes per point.

I generally compact data in strings, using 7 bit ascii. So some coding is needed. I first differenced the data. Colors tend to vary smoothly, so most differences are within a range of 64. These can be sent within a byte, leaving some characters over to signal exceptions. One is land, so a few bytes can be used to describe an often long stretch. The data is being listed in latitude bands. Differences that don't fit within the range are expressed as base 64 numbers. That gets the data down to about 700 Kb.

WebGL minimising

GL has always been extravagant with memory to gain performance. People who advise on WebGL follow this custom. I used for a while the R package RGL. For this task they would use triangles with node coords as 3 floats (32 bit) and colors as 4. Since each point is in six triangles, it entails 42 floats.

That's where I started, but all sorts of things broke down. Firebug (which I rely on) groaned, and overflows happened within WebGL itself.

The best remedy of course would be indexing. The GPU system is parallel, so this is probably bad for performance, but for this kind of thing, we can give up some. WebGL allows it, but the index variables must be one or two byte integers. This seems very odd to me, since the point of indexing is to economise with large objects. People work around it with subdivided objects, and that's an option here, but I would have needed at least sixteen such objects.

So I tried other WebGL facilities. The first was using bytes instead of floats for the rgb in color, and dropping the transparency alpha. That gained a factor of two. Then I used the GL option of triangle strips, which cuts the repetition of nodes. But still each has to be done stated twice.

Coastal issues

I don't use any mapping data. It's not easy, anyway, to beat the 25km resolution of the AVHRR data. But the triangularisation has a grain, and if the coastline goes across it, there is a sawtooth representation. I had developed a neat way of switching the grain, which got rid of this. Unfortunately, that doesn't go well with the use of triangle strips, which tend to enforce the grain. I can get around this with introducing degenerate triangles, but decided to leave that for another day.

No comments:

Post a Comment