MetLib User Guide

January 10, 2012

Contents

Introduction
Library Methods
Utility Methods
Examples

Introduction


MetLib, short for Metorological Library, is a collection of Numpy methods that perform meteorological operations on gridded data. With these tools, forecasters can create derived weather elements such as vorticity, termperature advection, or moisture convergence from within the SmartTool framework.  These methods should help forecasters more easily inject science into the process of weather forecasting with the Graphical Forecast Editor.

The library currently contains the basic building blocks from which very complex yet meteorological techniques can be developed. As the library is used in the field and new additions are requested, the library will continue to grow.

Currently the MetLib is a prototype and is experimental.  Use at your own risk.

Library Methods

This section describes the list of MetLib methods.

centeredDifference(grid, axis)

The centeredDifference method calculates a partial derivative along the specified axis.  It uses a centered differencing technique to calculate the difference in value at each grid point from its neighboring grid point.  This method is not meant to be used in a SmartTool, but is documented here for completeness.  See below for methods that use the centeredDifference method  to calculate derivatives.

forwardDifference(grid, axis)

The forwardDifference method calculates forward difference derivative.

backwardDifference(grid, axis)

The backwardDifference method calculates backward difference derivative.

d_dx(grid)

The d_dx method calculates a partial derivative along the x axis.  For most grid projections this is also the west-east direction.  The returned grid represents the gradient of the specified grid along the x-axis only.  These values are not scaled to your particular GFE domain or grid size.  To calculate a true gradient you will need to divide by a spacingGrid so that your grid spacing is taken into account.

d_dy(grid)

The d_dy method calculates a partial derivative along the y axis.  For most grid projections this is also the north-south direction.  The returned grid represents the gradient of the specified grid along the y-axis only.  These values are not scaled to your particular GFE domain or grid size.  To calculate a true gradient you will need to divide by a spacingGrid so that your particular grid spacing is taken into account.

d_dz(grid)

The d_dz method calculates a partial derivative along the z axis.  For most grid projections this is also the up-down direction.  The returned grid represents the gradient of the specified grid along the z-axis only.   Note that for this method to work properly you must specify a grid of at least 3-dimensions.  If you specify a grid of smaller dimensions, an error will occur.  Also note that to calculate a true vertical gradient, you must also divide the result from this method by the appropriate scaling factor.  For example, if your gridded data has a vertical resolution of 25 millibars, then you should divide the result by 25 mb.

d_dt(grid)

The d_dt method calculates a partial derivative along the time axis. For this method to work properly, you must specify a 4-dimensional grid.   If a grid of fewer than 4 dimensions is specified, an error will be reported.  Note that for GFE grids the time dimension is outer loop dimension. In all cases, you will need to construct your own 4-dimensional grid before calling this method. Standard GFE methods only return 3-dimensional grids at best.

gradient(scalarGrid)

The gradient method uses the d_dx and d_dy methods to calculate the horizontal vector gradient of a scalar grid. The result is returned as two grids,  the dx-component and the dy-component.  To display the gradient on the GFE, you must first convert the x and y components to a magnitude and direction (just like wind) and specify a grid of type VECTOR.   This method is often referred to as the DEL operator in many books and journals.  The entire implementation appears below:

return (d_dx(grid), d_dy(grid))

divergence(windGrid)

The divergence method calculates the horizontal divergence of the specified wind field.  Note that the wind field must be specified in u and v components - NOT magnitude and direction.  Use the SmartScript method MagDirToUV to convert magnitude and direction to u and v components. The implementation appears below:

    u, v = Wind
    return d_dx(u) + d_dx(v)

vorticity(windGrid)

The vorticity method calculates the vorticity of the specified wind field.  Note that the wind field must be specified in u and v components - NOT magnitude and direction.  Use the SmartScript method MagDirToUV to convert magnitude and direction to u and v components. The implementation appears below:

    u, v = Wind
    return d_dx(v) - d_dy(u)

advection(windGrid, scalarGrid)

The advection method calculates the advection of the specified scalar grid by the specified wind grid.  Notee that the wind grid must be specified as u and v components NOT as magnitude and direction.  Use the SmartScript method MagDirToUV to convert magnitude and direction to u and v components. The implementation appears below:

    return -dot(windGrid, gradient(scalarGrid))

dot(vectorGrid1, vectorGrid2)

The dot method calculates the dot product from the specified vector grids.  Again note that both vector grids must be specified as u and v components NOT magnitude and direction.  The implementation for dot appears below:

    return vectorGrid1[0] * vectorGrid2[0] + vectorGrid1[1] * vectorGrid2[1]

Utility Methods

The following methods provide grids that are often useful when making meteorological calculations.

getLatLonGrids(gridLoc)

The method getLatLonGrids returns a tuple of two grids, the first is the latitude at every grid point while the second is the longitude at every grid point.

Note that this method requires the gridLocationof the GFE.  You can get  this grid by including the following code:

gridLoc = self.getGridLoc()


from within any SmartTool.

makeSpacingGrid(gridLoc)

The makeSpacingGrid method calculate the grid size at every grid point.  For most typical GFE domains the value at every grid point is so close that using a constant value would likely work well.  But for other projections, the distance between your grid points may vary enough that using this grid produces superior results.  A note of caution: for conformal projections (like Grid211) the difference between the x-gridSize and the y-gridSize are virtuall identical.  However for non-conformal projections, such as Mercator, you will want to use a different makeGridSpacing method that returns two grids, one for the x-gridSize and one for the y-gridSize.  This method will be included in a future version of MetLib.

Note that this method requires the gridLocationof the GFE.  You can get  this grid by including the following code:

gridLoc = self.getGridLoc()

from within any SmartTool


makeCoriolisGrid(latGrid)

Occasionally, you may need the Coriolis accleration in your calculations.  MakeCoriolisGrid returns a grid of Coriolis acceleration at each gid point.  It uses the latitude grid from getLatLonGrids.

Note that this methods requires a grid of latitude at each grid point.  You can get this grid by including the following code:

latGrid, lonGrid = getLatLonGrids(self.getGridLoc())

from within any SmartTool.

Examples

To use any of the MetLib methods, you will need to import the MetLib module, just like SmartScript.  However, because it is a module and not part of the Tool class, you will not have to prepend "self." in front of every MetLib method.  To import the MetLib module insert this line into your SmartTool:

from MetLib import *

That import statement will grant you access to all of the methods documented above, without having to prepend "self." or "MetLib." in front of every MetLib method call.

Note that in some of the tools that follow, there are examples that show you how to access the geographical information so that you can properly scale your calculations to the appropriate units.  These examples use the GridTimeRange variable for simplicity in creating a new grid on the GFE that you can see.  In cases where D2D data is accessed, you will need to select a timeRange that contains the specified D2D model grid in order for the tool to work.  If you load the D2D grid that will be used in the tool, you will be able to precisely see when the grids are currently available and select the appropriate timeRange on the GFE.

Below we list a few working SmartTools that use some of the MetLib methods.

# ----------------------------------------------------------------------------
ToolType = "numeric"
WeatherElementEdited = "variableElement"
from Numeric import *

# Set up Class
import SmartScript
from MetLib import *   # Here's where MetLib is imported

class Tool (SmartScript.SmartScript):
    def __init__(self, dbss):
        SmartScript.SmartScript.__init__(self, dbss)

    def execute(self, variableElement, GridTimeRange, T):
        "Test SmartTool illustrating MetLib methods"

        grad = gradient(T)  # calculate the temperature gridient

        # display the gradient as a weather element created "on the fly"
        self.createGrid("Fcst", "TempGradient", "VECTOR", grad, GridTimeRange,
                        minAllowedValue=-10.0, maxAllowedValue=10.0)

        return variableElement
# ----------------------------------------------------------------------------

# ----------------------------------------------------------------------------
ToolType = "numeric"
WeatherElementEdited = "variableElement"
from Numeric import *

# Set up Class
import SmartScript
from MetLib import *
## For available commands, see SmartScript

class Tool (SmartScript.SmartScript):
    def __init__(self, dbss):
        SmartScript.SmartScript.__init__(self, dbss)

    def execute(self, variableElement, GridTimeRange):
        "Test tool for MetLib methods"

        # get the model's 500 mb  wind grids
        modelName = self.getSiteID() + "_D2D_GFS40"
        modelLevel = "MB500"
        modelWind = self.getGrids(modelName, "wind", modelLevel, GridTimeRange)

        # get some geo info
        gridLoc = self.getGridLoc()
        latGrid, lonGrid = getLatLonGrids(gridLoc)
        spacingGrid = makeSpacingGrid(gridLoc)
        coriolisGrid = makeCoriolisGrid(latGrid)

        # make the calculations and unit conversions and scaling
        u, v = self.MagDirToUV(modelWind[0], modelWind[1])
        vort = (vorticity((u, v)) + coriolisGrid)/ spacingGrid
        vort = vort * 100000  # scaling factor so display works better
        self.createGrid("Fcst", "500MBVorticity", "SCALAR", vort, GridTimeRange,
                        descriptiveName=None, timeConstraints=None,
                        precision=1, minAllowedValue=-200,
                        maxAllowedValue=200)


        return variableElement

# ----------------------------------------------------------------------------

# ----------------------------------------------------------------------------
ToolType = "numeric"
WeatherElementEdited = "variableElement"
from Numeric import *

# Set up Class
import SmartScript
from MetLib import *
## For available commands, see SmartScript

class Tool (SmartScript.SmartScript):
    def __init__(self, dbss):
        SmartScript.SmartScript.__init__(self, dbss)

    def execute(self, variableElement, GridTimeRange):
        "Test tool for MetLib methods"

        # get the model's 500 mb temp and wind grids
        modelName = self.getSiteID() + "_D2D_GFS40"
        modelLevel = "MB500"
        modelWind = self.getGrids(modelName, "wind", modelLevel, GridTimeRange)
        modelT = self.getGrids(modelName, "t", modelLevel, GridTimeRange)

        # get some geo info
        gridLoc = self.getGridLoc()
        latGrid, lonGrid = getLatLonGrids(gridLoc)
        spacingGrid = makeSpacingGrid(gridLoc)
        coriolisGrid = makeCoriolisGrid(latGrid)

        # make the calculations and unit conversions
        u, v = self.MagDirToUV(modelWind[0], modelWind[1])
        tAdvection = advection((u, v), modelT) / spacingGrid
        tAdvection = tAdvection * 3600 * 12  # convert to deg/12 hours
        tAdvection = clip(tAdvection, -200.0, 200.0)
        self.createGrid("Fcst", "Tadvection", "SCALAR", tAdvection, GridTimeRange,
                        descriptiveName=None, timeConstraints=None,
                        precision=1, minAllowedValue=-200,
                        maxAllowedValue=200)


        return variableElement

# ----------------------------------------------------------------------------