Visualization in Google Earth
- Back to the WRF-SFIRE user guide.
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.
The code described on this page is maintained in a repository at
. Contained within it is a simple script
for generating KMZ files for visualizing the heat flux from a fire simulation for users
that do not wish to customize the output. The
script requires python modules, matplotlib, scipy, and
netCDF4. The script takes a single
argument, the WRF output file,
python nc2kmz.py <wrfout file>.
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)/float(infected.shape) 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
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
In : from Scientific.IO import NetCDF In : file=NetCDF.NetCDFFile('episim_0100.nc','r') In : lat=file.variables['latitude'] In : lon=file.variables['longitude'] In : lat[-1],lat,lon[-1],lon Out: (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.
Creating preloaded WRF-Fire animations
This is only for users who have older versions of Google Earth. If you have Google Earth 6, loading multiple images from KMZ files is no longer an issue.
python nc2kmz_GE5.py <wrfout_filename>
The preloading functionality is an extension of the ncEarth module that accomplishes preloading the set of images that is in KMZ files by adding a static copy of the animated GroundOverlays. The static copy of GroundOverlays is without the TimeSpan element. When opening preloaded animation KMZ files, Google Earth automatically loads all the static GroundOverlays which caches the images that are needed in the animation, and when it finishes loading the static GroundOverlays, the timeline slider will appear on the left top corner of the screen for playing the animation. Loading time depends on the number of GroundOverlays in the animation, and if the animation is very large in size, Google Earth may appear frozen while loading. Unfortunately, Google Earth does not provide a way to display a message to the users while loading.
Creating WRF-Fire animation legend
For conveying information, we will need a legend for the animation. First of all, get the script here to generate the image for the legend. Use it as the following example:
import colorbarImg colorbarImg.getImages('wrfout.nc','FGRNHFX')
Passing the name of a dataset and the variable name, and the resulting images will be stored in a subfolder called “colorbarImages”. After selecting a colorbar image, we can use ScreenOverlay to display the legend in a fixed position on the screen. Here are some examples of ScreenOverlay.
Refers to an image at given URL:
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <ScreenOverlay> <name>Legend name</name> <color>ffffffff</color> <Icon> <href>http://server.com/legend.png</href> </Icon> <overlayXY x="0" y="1" xunits="fraction" yunits="fraction"/> <screenXY x="0" y="1" xunits="fraction" yunits="fraction"/> <rotationXY x="0" y="0" xunits="fraction" yunits="fraction"/> <size x="1" y="-1" xunits="fraction" yunits="fraction"/> </ScreenOverlay>
Refers to an image in the KMZ file folder:
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <ScreenOverlay> <folder> <name>Legend name</name> <color>ffffffff</color> <Icon> <href>files/legend.png</href> </Icon> <overlayXY x="0" y="1" xunits="fraction" yunits="fraction"/> <screenXY x="0" y="1" xunits="fraction" yunits="fraction"/> <rotationXY x="0" y="0" xunits="fraction" yunits="fraction"/> <size x="-1" y="-1" xunits="fraction" yunits="fraction"/> </folder> </ScreenOverlay>
<Icon> element points to the image to be used. This image file can be located on a file system or on a web server. To position the overlay, change the x and y values of the
overlayXY maps a point in the image to a point on the screen specified by
screenXY, the unit for x and y values can be one of three units: pixels, fraction, and insetPixels. Also the values can be specified in different ways, for example x can be in fraction and y can be in pixels. The
<size> element determines the size of the ScreenOverlay, vaule of -1 indicates to use the images’ original dimension.
For more detailed explanation of ScreenOverlay’ elements, see KML reference document.