Visualization in Google Earth
Google Earth is proprietary software from Google allowing the user to explore 3D imagery of the earth's surface. Using its native support for kml files, it is possible to overlay images from numerical simulations onto the surface of the earth. However, Google Earth is not designed to be a visualization suite for numerical models. It can't, for example, create a pseudo color image from raw data. One must generate a bitmap image (jpg or png) of the data first before it can be used in Google Earth. Once that is done, it is a simple matter of creating a kml file which tells google where to display the image on the ground.
Generating an image from raw data
When one generates a pseudocolor image from raw data, for example in Matlab using the imshow
command, the image will usually contain a border with titles and axis labels. In order to align the image properly in Google Earth, we want just the image itself without any borders whatsoever. The easiest way to do this would be to open the image in Gimp and crop it manually; however, this is not suitable for generating a large number of visualizations or for an automated system.
Using python and matplotlib
The python programming language contains a large number of packages useful for scientific computing and visualization. In particular, matplotlib combines the numerical processing capabilities of numpy with a full-featured 2D plotting package, which is very similar to Matlab's 2D plotting capabilities. In this example, we will use the function imshow to generate a psuedo color image from some data in an EpiSim output file. In order to run this example yourself, you must have python with the matplotlib and Scientific Python (for reading the output NetCDF files) packages installed.
When we run EpiSim, we are left with a series of NetCDF files as output. These files contain the raw data from the model for a single time step. We want to create an image of the Infected
variable from file episim_0100.nc
to overlay onto Google Earth. We start by reading the file using the Scientific Python package.
from Scientific.IO import NetCDF file=NetCDF.NetCDFFile('episim_0100.nc','r') infected=file.variables['Infected']
Now we load the matplotlib package, and create a new figure window. Ordinarily, doing this is unnecessary. Because we want the image to contain no borders, we must initialize the figure window to contain only the figure axis. Note that the figure must be created with the correct aspect ratio, or the image will contain borders. We will use a constant width of 5 inches and find the correct height by multiplying the aspect ratio of the input data (the number of rows divided by the number of columns of the variable).
import pylab width=5 height=width*float(infected.shape[0])/float(infected.shape[1]) fig=pylab.figure(figsize=(width,height)) fig.add_axes([0,0,1,1])
This should have created an empty figure window. We are now able to generate image using the imshow
command. Note that imshow
draws the figure from top to bottom (like an image) so we must flip the data vertically (using flipud
) prior to displaying. Also, we want to visualize the data on a log color scale, so we will take the logarithm of the data (log 0
will show up as white in the figure).
data=pylab.flipud(infected) data=pylab.log(data) pylab.imshow(data)
Finally, we will turn off the axis to remove any remnants of tick marks from the display axis, and save the file to a png image named Infected.png
.
pylab.axis('off') pylab.savefig('Infected.png')
You should now have an image that is ready to use as an overlay in Google Earth.
Creating a kml file
External images can be included into Google Earth in a number of different ways. What we are interested in is displaying our image over the ground. This is what is known as a GroundOverlay. A minimal kml file which will do this with the Infected.png
image we generated above is as follows.
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <GroundOverlay> <name>Infected</name> <Icon> <href>Infected.png</href> </Icon> <altitude>0.0</altitude> <altitudeMode>clampToGround</altitudeMode> <LatLonBox> <north>14.958334</north> <south>-10.000000</south> <east>40.958336</east> <west>16.000000</west> <rotation>0.0</rotation> </LatLonBox> </GroundOverlay> </kml>
The primary components of this file are the name of image as it is displayed in the Google Earth menu, the Icon
key which tells where to find the image, the altitudeMode
key tells it to stretch the image of the ground. Finally, the LatLonBox
tells Google Earth where to put the image. The image is assumed to be defined on a regular latitude/longitude grid (not projected). The keys give the lines of latitude and longitude where the edges of the image should be placed. For the EpiSim output files, this can be found by looking beginning and end of the variables latitude
and longitude
.
In [1]: from Scientific.IO import NetCDF In [2]: file=NetCDF.NetCDFFile('episim_0100.nc','r') In [3]: lat=file.variables['latitude'] In [4]: lon=file.variables['longitude'] In [5]: lat[-1],lat[0],lon[-1],lon[0] Out[5]: (14.958334, -10.0, 40.958336, 16.0)
Many more features for displaying overlays are available in the kml standard. See the documentation for further details.
Python Class for creating WRF-Fire animations
For a more complicated example of automating the creation of KML files from NetCDF, see the Python module ncEarth at [1]. This can easily be extended to provide more functionality or to output KML from other models. The following code can be used to display an animation of the heat flux from a WRF-Fire simulation using this module.
import ncEarth kmz=ncEarth.ncWRFFire_mov('wrfout') kmz.write('FGRNHFX')