User Defined Products in GR2Analyst 3

GR2Analyst 3's User Defined Product feature (UDP) allows users to create their own radar products similar to those built into GR2Analyst (e.g. VIL, MEHS, etc.). A UDP is a simple text file that describes the product and provides a small program (using the Radar Shader Language) that generates its output from a vertical column of radar data. UDPs are executed over a 360 x 230 grid (1° by 1 km bins). All base radar data products (BR, BV, SW, ZDR, CC, KDP) and NROT can be used in your shader. Shaders can be simple or complex.



Composite Reflectivity Shader

Composite Reflectivity can be generated by a very simple UDP:

//**********************************************************************
Product
 {
  Name     = "CR"    // product name is CR
  Category = "BR"    // it uses the BR category and color table
 }


//**********************************************************************
Program
 {
  return MaxBRaboveHGT(0);   // return the max reflectivity starting at zero height
 }


Here is the output from the UDP in a two-panel view with BR 0.5°:





Max ZDR Above -10°C Shader

A high ZDR above the freezing level could indicate a strong updraft, so we need a shader for that. It's more complicated than CR above because we need to enumerate the levels starting at -10°C and take the max value. We use the built-in ZDR category for this product:

//**********************************************************************
Product
 {
  Name     = "ZDR0"     // product name is ZDR0
  Category = "ZDR"      // it uses the ZDR category and color table

  min_br_required = 30  // only interested in columns with BR >= 30 dbz
 }


//**********************************************************************
Program
 {
  float max_zdr;       // declare variable to hold max value

  max_zdr = 0;         // initialize it to zero

  enumerate levels from HGTfromTEMP( -10 )    // enumerate starting at -10C
   {
    if( BRfromHGT( level.height ) > 30 )      // max only where BR > 30 dbz
     {
      max_zdr = max( max_zdr, ZDRfromHGT( level.height ) );
     }
   }

  return max_zdr;
 }


Here's a max trail for the max ZDR above -10C product showing its evolution prior to tornadogenesis in this event:




Vertically Integrated Ice Shader

Vertically Integrated Ice (VII) requires a more complex shader. The equations used are from the WDTD's page on VII in the MRMS:

WDTD Vertically Integrated Ice

There is no built in category for VII so we need to fully define it in our shader:

//******************************************************************************
//
// Product definition section for Vertically Integrated Ice. Gives the name for
//   it followed by a full definition of the data being generated (the Category).
//

Product
 {
  Name = "VII"        // Unique name for product

  Category
   {
    Missing = 0        // physical value for ND
    Minimum = 0        // category minimum value
    Maximum = 100      // category maximum value
    Units   = "VII"

    ColorTable        // color table for category
     {
      Units    = "VII"
      Step     = 5

      Color[40   ] =           rgb( 255, 255, 255 )
      Color[21.30] =           rgb( 110,   0, 210 )
      Color[17.00] =           rgb(  80,   0, 200 )                            // purple gradient
      Color[12.21] = gradient( rgb( 250,   0, 255 ), rgb(  90,   0, 202 ) )    // blue gradient
      Color[ 9.33] = gradient( rgb( 248,  26,  16 ), rgb( 106,   6,   4 ) )    // red gradient
      Color[ 6.33] = gradient( rgb( 250, 255,  16 ), rgb(  28, 158,   0 ) )    // yellow/green gradient
      Color[ 3.33] = gradient( rgb(  77, 255, 255 ), rgb(  58,   0, 255 ) )    // cyan/blue gradient
      Color[ 0   ] = gradient( rgb(  50,  50,  50 ), rgb( 190, 190, 190 ) )    // gray gradient
     }
   }
 }


//******************************************************************************
//
// Radar shader for VII. Uses the enumerate levels statement to walk upwards
//   through the tilts of BR, accumulating VII along the way. The return
//   statement applies the ugly scaling constant for VII. It also divides by
//   1000 to convert from grams to kilograms in the final output.
//

Program
 {
  float vii;

  vii = 0;                                                        // initialize sum to zero

  enumerate levels from HGTfromTEMP( -10 ) to HGTfromTEMP( -40 )  // enumerate data heights from -10C to -40C
   {
    float z;
    z = pow( 10, BRfromHGT( level.height ) / 10 );                // sample BR and convert from dbz to z
    vii += pow( z, 4 / 7 ) * level.depth;                         // integration step
   }

  return 0.006073394 / 1000 * vii;                                // apply messy constant, divide by 1000 to get kg
 }