This is an archived cached-text copy of the developerWorks article. Please consider viewing the original article at: IBM developerWorks



IBM®
Skip to main content
    Country/region [select]      Terms of use
 
 
    
     Home      Products      Services & industry solutions      Support & downloads      My IBM     
skip to main content

developerWorks  >  Open source  >

Develop your own weather maps and alerts

Process radar data with open source image processing tools to create custom alerts

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


Rate this page

Help us improve this content


Level: Intermediate

Nathan Harrington (harrington.nathan@gmail.com), Programmer, IBM

05 Jun 2007

Traditional weather reports will give notice of vague forecasts and severe weather alerts in your general area. The code and tools presented in this article will allow you to create precise detection zones so you can receive a page, SMS, or e-mail a few minutes before a precipitation event is likely to occur at the monitored location. Use GD and Perl for image processing of the NOAA WSR-88D radar data to create your own precipitation alerts for precise areas. Choose your notification method and let users know when the rain will begin and when it will clear.

The National Oceanic and Atmospheric Administration (NOAA) is a fantastic government agency responsible for the majority of the weather data in the United States. Using the publicly available and easily accessible reflectivity data from one of the WSR-88D class radar systems, this article will show you how to choose a location and set up weather-change alerts for a precise geographical area. Please note that this is not a substitute for severe weather alert systems or designed to produce reliable precipitation forecasts. Rather, this article presents code and processes for determining if it's likely to rain very soon in a specific area. Conversely, the same code is used to produce alerts when a no-precipitation window has opened, giving you a handy notice of when it's time to dash inside from your car.

Requirements

Hardware

Any PC manufactured after 2000 should provide plenty of horsepower for compiling and running the code in this article. The code presented here is a relatively simple image processing algorithm using GD. If you want to monitor multiple locations with subsecond response times, you'll need a fast processor. The rest of us should be fine with anything Pentium II® or later.

Software

Perl and GD are a must for this article, although if you have a preferred image processing tool suite, you can modify the algorithms used here to perform effectively in any number of environments. You'll also need an image-compositing tool, such as The Gimp, to build a geophysical map of the radar's environment and to choose a set of pixel coordinates specifying your location. In addition, it's handy to have a good command-line download tool, such as wget. Check Resources for links.



Back to top


Image acquisition

The WSR-88D class radar systems have many acquisition modes for developing data on atmospheric precipitation. The most commonly used form of radar energy return mapping is the Base Reflectivity graph. We will use this graph for the processing of localized precipitation information. To begin, visit NOAA.gov, and enter your city and state for a forecast. Click the radar image for your localized area, and you will see an image like that shown below.


Figure 1. Base reflectivity Web page example
Base Reflectivity web page example

The radar image shown is actually composed of layers you can download separately. Downloading RIDGE Radar Images describes the various layers and how to download them. For our example, we'll need the topographical, highways, and county maps to accurately identify the precise location to track. You'll only have to download these layers once, and you'll be able to reuse them later. Listing 1 shows the various images you'll need to download if you live in central North Carolina. Consult the NOAA documentation to find the radar designation and appropriate URLs for your area.


Listing 1. Radar image overlays Central North Carolina
                
County Outlines: http://www.srh.noaa.gov/ridge/Overlays/County/Short/RAX_County_Short.gif
Highway: http://www.srh.noaa.gov/ridge/Overlays/Highways/Short/RAX_Highways_Short.gif
Topographical relief: http://www.srh.noaa.gov/ridge/Overlays/Topo/Short/RAX_Topo_Short.jpg

With these layers downloaded, you can combine them with the base reflectivity image to produce a more easily readable image map. Here is the radar image for the central North Carolina area. Download the equivalent layers and radar return image for your area, and you'll be ready to move on to the next step.



Back to top


Selecting your location on the map

Fire up The Gimp or your image manipulation tool of choice and combine the overlays you downloaded for your area. I recommend applying the overlays in the following order: topographical, counties, highways. Do not include the radar base reflectivity image as it can make precise area location more difficult. Zoom in on your general area and use your mouse to identify the precise location you want to monitor. Note the pixel coordinates as they will be used as the basis for the monitoring area in the image-processing code. Figure 2 shows a screenshot from The Gimp window, as the Research Triangle Park area in central North Carolina is identified. The precise coordinates in this case are shown in the bottom left-hand corner as 263,258.


Figure 2. Precise location identification
Precise location identification



Back to top


Image artifact considerations

A common occurrence for the base reflectivity data is to show the equivalent of light precipitation where there is in fact clear skies. This explanation of this behavior is beyond the scope of this article, but we need to deal with these false positives in order to reliably detect when a precipitation event is likely to occur. Figure 3 shows a sample base reflectivity image on a clear day in central North Carolina.


Figure 3. Clear day base reflectivity false positives
Clear day base reflectivity false positives

As you can see from the radar data, there appears to be light precipitation within a 30-mile radius of the radar antenna. A quick look outside shows this is obviously not the case, and the program shown below will compensate for this behavior by only detecting precipitation events of a certain threshold. Precipitation events in the "Light" classification have a base reflectivity of between 0 and 15 DBZ. This seems to correspond well to the reflectivity range of the false positives, so the program described below will consider anything of higher reflectivity to be a trackable precipitation event. Specifically, any pixels that are green, yellow, or red will be considered precipitation events as they pass through the detection area.



Back to top


Using GD for simple yellow, green, and red reflectivity acquisition

With your selected pixel coordinates and a single-layer base reflectivity map, the logical process for detecting precipitation near a spot on the map is straightforward. First, scan the reflectivity data in the immediate area around the detection coordinates, allowing for precipitation front movement from any direction. If the scanned data indicates reflectivity above "low" (the presence of green, yellow or red pixels), consider the status to be "raining." If there is no reflectivity above the "low" threshold, consider the status to be "clear." The omni-directionality of the detection algorithm is important to ensure the capability for detecting precipitation gaps in a developing storm system.

The getPrecipState.pl program shown in Listings 2 and 3 uses Perl and GD to implement the high-level logical process:


Listing 2. getPrecipState.pl Section 1
                
#!/usr/bin/perl -w
# getPrecipState.pl - process WSR-88D N0 (base reflectivity) data to indicate
#                     precipitation status, such as 'raining' or 'clear'
use strict;
use GD;

die "specify file name, X pixel, Y pixel, distance, threshold " unless @ARGV == 5;
my( $fname, $pointX, $pointY, $distance, $threshold ) = @ARGV;

my %colorList =( "2,253,2"     => "lightGreen 20DBZ",
                 "1,197,1"     => "mediumGreen 25DBZ",
                 "0,142,0"     => "darkGreen 30DBZ",
                 "253,248,2"   => "lightYellow 35DBZ",
                 "229,188,0"   => "mediumYellow 40DBZ",
                 "253,139,0"   => "darkYellow 45DBZ",
                 "253,0,0"     => "lightGreen 50DBZ",
                 "212,0,0"     => "mediumGreen 55DBZ",
                 "188,0,0"     => "darkGreen 60DBZ",
                 "248,0,253"   => "lightPurple 65DBZ",
                 "152,84,198"  => "mediumPurple 70DBZ",
                 "253,253,253" => "takeCover! 75DBZ" );

my $radarMap = newFromGif GD::Image( "$fname" ) || die "bad image file $fname";

The first section of getPrecipState.pl ensures that the program has the correct number of variables to process. After defining a simple hash of the colors considered to be valid precipitation, the image specified is loaded from disk. Note that if you want to track strong reflectivity signals only in the N0 map, simply remove the green and yellow colors from the colorList hash.


Listing 3. getPrecipState.pl Section 2
                
my $startCol = $pointX - ($distance/2);
my $startRow = $pointY - ($distance/2);
my $endCol   = $pointX + ($distance/2);
my $endRow   = $pointY + ($distance/2);

my $colN = $startCol;

my $precipCount = 0;

while( $colN <= $endCol )
{
  my $rowN = $startRow;
  while( $rowN <= $endRow )
  {
    my $index = $radarMap->getPixel( $colN, $rowN );
    my( $r, $g, $b ) = $radarMap->rgb($index);
    if( exists( $colorList{"$r,$g,$b"} ) )
    {
      $precipCount++;
      if( $precipCount >= $threshold ){ $colN = 700; $rowN = 700 }
    }
    $rowN++;
  }#column

  $colN++;
}#row

if( $precipCount >= $threshold )
{
  print "$fname is raining\n" ;
}else
{
  print "$fname is clear \n";
}

The remainder of the getPrecipState.pl code shown in Section 2 sets up a square detection area bounded by the start and end Col|Row variables. The next two while loops simply scan the detection area for precipitation pixels as defined by their color match to those specified in the colorList hash variable. If enough precipitation pixels have been counted to exceed the threshold parameter, exit the loops and write the "raining" status. If there are too few precipitation pixels to exceed the threshold parameter, print the "clear" status.

With your base reflectivity layer downloaded as shown above, run the program with the command perl getPrecipState.pl <radar_image> <X coord> <Y Coord> <distance> <threshold>. For example, if your radar image is from the central North Carolina WSR-88D station, your location coordinates are 263,258 and you want to detect the presence of moderate or greater precipitation within an approximately 5-mile area around the detection zone, you would specify a command of perl getPrecipState.pl RAX_N0R_0.gif 263 258 10 40.



Back to top


State monitor with rules

Now that you have your rain/clear processor completed, you can tie the output to a simple state monitor to produce alerts based on your rules. For example, let's assume you want an e-mail notification when rain is in the immediate area, and an on-screen notification pop-up after it has passed. The following configuration file will send an e-mail using mutt for the rain warning and pop-up a message box to the local display for 10 seconds when the rain has passed.

raining ## mutt -s "rain proximity alert" 919749089?@cingularme.com < /dev/null
clear ## kdialog --passivepopup "The rain has passed" 10

To process these notification configuration options correctly, we'll need a program that determines the initial state of the detection zone, then monitors the zone for changes in status and sends the appropriate output. Listing 4 shows the stateMonitor.pl program.


Listing 4. stateMon.pl Section 1
                
#!/usr/bin/perl -w
# stateMon.pl - simple monitoring of precipitation state
use strict;
my %cmdHash = ();
my $initialState = "null";
eval
{
  open(STATE,notify.state) or die "could not open state file";
    $initialState = <STATE>;
  close(STATE);
};

if( $@ =~ /could not open state file/ )
{
  open(STATE,">notify.state") or die "can't open state file for writing";
    print STATE "null";
  close(STATE);
}#file not found error

open(CFG,notify.config) or die "can't open notification configuration";
  while(<CFG>)
  {
    my( $keyword, $command ) = split " ##";
    $cmdHash{$keyword} = $command;
  }
close(CFG);

The first section will declare variables and attempt to load the previous configuration from the notify.state file. If the file does not exist (as determined by the file open error), write the "null" state to the file. The notify.config file is then processed to load the commands to run upon each state being reached. Listing 5 shows the remainder of the stateMon.pl program.


Listing 5. stateMon.pl Section 2
                
while(my $status = <STDIN>)
{
  open(STATE,">notify.state") or die "can't open state file for writing";
    print STATE "$status";
  close(STATE);

  for my $keyword ( keys %cmdHash )
  {
    if( $status =~ /$keyword/i )
    {
      last if( $initialState eq "null" );
      if( $initialState !~ /$status/i )
      {
        my $cmd = `$cmdHash{$keyword}`;
      }#if status is not initial state
    }#if status and keywork match
  }#for each keyword

}#while stdin

The standard "while" type loop starts by reading the output from the getPrecipState.pl program. The current state is then written to the notify.state file, which saves the state for the next read. Each key read from the notify.config file is then processed. If the current status matches a key from the notify.config file as stored in the %cmdHash variable, continue the processing. If the initialState is "null" (a previous state had not been recorded), exit the loop. Otherwise, if the current state does not match the recorded state, run the command specified.

Take the following case as an example:
The program starts, and the notify.state file does not exist, so it is created with the contents "null". The "clear" status has been passed in by the getPrecipState.pl program, so the first section in Listing 5 will write "clear" into the notify.state file. The keys specified in %cmdHash are processed, but because the initialState was set to "null", the loop is exited, and no commands are run. On the next pass, the stateMon.pl program will read the "clear" status from the notify.state file, and if the getPrecipState.pl program passes in a "raining" status, the appropriate notification will be sent to the specified e-mail address.

To use the stateMon.pl program, simply pipe the output of the getPrecipState.pl program into the stdin of stateMon.pl, like so: perl getPrecipState.pl RAX_N0R_0.gif 263 258 10 40 | perl stateMon.pl.

Keep in mind that you can modify the getPrecipState.pl program and the notify.config alert descriptions file to support any number of events. If you'd like to receive a notice when the notification zone receives a high percentage of rainfall compared to the surrounding areas, it's a simple matter of changing the processing algorithms of the getPrecipState.pl program and printing out a different keyword to be matched by the contents of the notify.config file.

Also note that if you want to reset the status of the stateMon.pl operations (such as raining, clear or null), simply delete the notify.state file or change the contents manually. This will allow you to reset the status of the detection system based on other factors, such as wind speed or computed cloud cover.



Back to top


Full precipitation monitoring configuration

Share this...

digg Digg this story
del.icio.us Post to del.icio.us
Slashdot Slashdot it!

With your selected radar image, geographical coordinates in pixel (X,Y) form, and the programs described above, you can create a simple precipitation and alert-clearing system. A basic configuration approach is to use wget (available for UNIX® and Windows®) and a scheduler, such as cron, to automatically download the WSR-88D base reflectivity image for your area every 5 minutes. Use the same scheduler to run the getPrecipState.pl command with the most recent image and pipe the output to the stateMon.pl program. Just like that, you'll receive messages as precipitation events approach, as well as when the rain will clear. Very handy if you want to know when to run outside to put the top up on your convertible or when a break in the rain will allow you to run out and check your snail mail without getting drenched.

This approach to radar image processing is useful for precipitation related messages, as well as developing data on various weather-related events. You can use slightly modified versions of this code to track precipitation trends over a broad time range. Another option is to change the bounding areas to provide simple rain gate monitor, in order to find out if it has rained on your favorite park bench in the past few hours, before you head for the picnic.




Back to top


Download

DescriptionNameSizeDownload method
Sample codeos-weathermaps-radarProc_0.1.zip1.5KBHTTP
Information about download methods


Resources

Learn
  • The National Oceanic and Atmospheric Administration explains the WSR-88D radar system.

  • CPAN hosts the GD Image Processing Perl module.

  • For automated file downloads, try wget for UNIX variants and Windows.

  • To determine your pixel coordinates in a layered radar image, try The Gimp.

  • " Enable C++ applications for Web services using XML-RPC" is a step-by-step guide to exposing C++ methods as services.

  • Browse all the open source content on developerWorks.

  • To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.

  • Stay current with developerWorks' Technical events and webcasts.

  • Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.

  • Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.

  • Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.


Get products and technologies
  • Innovate your next open source development project with IBM trial software, available for download or on DVD.

  • Download IBM product evaluation versions, and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

Discuss


About the author

Nathan Harrington is a programmer at IBM currently working with Linux and resource-locating technologies.




Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 


Back to top



    About IBM Privacy Contact