Monday, May 13, 2013

Tutorial: Two different methods for array syntax in GrADS

Arrays can be an extremely useful tool when using loops in GrADS.  Arrays reduce the number of lines in your code by a potentially large amount.  For example, if you wanted to plot soundings at a number of different locations: Without arrays, you would either need to have a separate segment of code for each location, or put a bunch of conditional statements in a loop to determine which location to set your coordinates to.  With arrays however, you can simply point to each new location using one single block of code, and no conditional statements.  If you are at all familiar with computer programming, in any language, you are almost certainly aware of the benefits of arrays.  This tutorial will be fairly short, and provide you with an idea of how to use the different array syntax methods in GrADS.

So basically, GrADS allows you to use arrays that are really only useful in loops, or potentially conditional statements.  The arrays in GrADS can't be used in liner algebraic operations, at least not easily.  I suppose you could put something together that might work, but then again what would be the point?  But in terms of telling the program to point to certain array values, the array syntax in GrADS is plenty sufficient.  There are two different methods to declaring and using arrays in GrADS that I work with.  I will explain each method, and give a little bit of information regarding their uses, including a couple of examples.

Method 1:

The first array syntax in GrADS uses the period (.) to indicate array values.  This is the simplest way to do arrays in GrADS, and I have found it sufficient nearly 100% of the time for what I want to do.  It is important to use the period syntax, instead of other possible separators (e.g., the underscore), as the period will separate the name and number in a loop.  The below example shows three different array expressions, one correct and two incorrect.

    array.1=5    ;*Correct
    array_1=5  ;*Incorrect
    array1=5    ;*Incorrect

    i=1


    say array.i
    say array_i
    say arrayi

The output from the following will be:

    5
    array_i
    arrayi

Basically, the period allows the variable "i" to be read as the number, the other two syntax expressions simply read the "i" as part of the variable name.

A few other notes about this GrADS array syntax: It is important to know that the array syntax here is very basic, and you aren't really declaring "arrays", what you're doing is simply declaring a bunch of variables, each with a period in the suffix, and then pointing to the names separately depending on the value of the suffix.  So sticking with the above example, these commands do not work:

   array=[5, 4, 3, 2, 1]  ;*No!

   say array.1
   say array.2

This does NOT output:

   5
   4

In fact, this script won't even run, you will just get an error  Also, this is no good:

  array.1=5
  array.2=4
  array.3=3

  say array

While this code will not give you an error if you try to run it, the output will NOT be:

  5 4 3

it will instead be:

  array

Get the idea?  Basically, you are just naming stuff, not really declaring arrays in the traditional sense.  That's pretty much it for this array syntax.  Now, this syntax can be exploited in a number of different ways, you can do 2D, or 3D or nD arrays, as long as each value is separated by a period.  Also, the values after the period do not necessarily have to be numbers.  The below examples will show you a few possible array expressions.

Basic Example: 

   x.1=5
   x.2=6
   x.3=15
 
   i=1
   while(i<=3)
      say x.i
      i=i+1
   endwhile

output:

   5
   6
   15

2D Array:

    x.1.1=15
    x.1.2=14
    x.2.1=12
    x.2.2=10

    i=1
    while(i<=2)
       j=1
       while(j<=2)
          say x.i.j
          j=j+1
       endwhile
       i=i+1
    endwhile

output:

   15
   14
   12
   10

 
Array Using Words:

x.array=15
word='array'

say x.word

output:

    15


That's it for the first method of arrays in GrADS, now onto the 2nd method!

Method 2:

This method is a little bit trickier to follow, but gives you a little better simulation of normal array syntax.  That being said, this part of the tutorial is actually much shorter than the above, as there aren't really as many variations of it.  This method, is basically to use the 'subwrd' command to point to values in a specified variable.  The 'subwrd' command basically scans a string and breaks it up into values separated by the space.  All you need to do is supply the function with the name of the string, and the word you are looking for.  For example, the code:

    array='5 10 15 20 25 30'
    say subwrd(array,4)
   say subwrd(array,1)+subwrd(array,2)

Would output the 4th word from this variable:

    20
    15

One of the benefits of using this syntax is that you can print out the array as a whole using the say command.  Another benefit is that you can really reduce the number of lines in your script this way vs. the 1st method.  Also, since GrADS is pretty good about automatically converting strings to floats, you can declare a string of numbers, and still do mathematical operations with each number. One drawback is that you can't really do multidimensional arrays this way.  Also if you are using names, you can't include names with spaces in them, since the 'subwrd' command uses spaces as delimiters between each value.  That being said, this method can be quite good for looping through lists.  A quick example is below:

Example:

    places='Home Store Work Park Earth'
    say places
    i=1
    while(i<=5)
       say 'Place 'i': 'subwrd(places,i)
       i=i+1
    endwhile

Output: 

    Home Store Work Park Earth
    Place 1: Home
    Place 2: Store
    Place 3: Work
    Place 4: Park
    Place 5: Earth



So, I think that wraps up the array syntax in GrADS.  Hopefully this tutorial gave you a good introduction and some good insight to using arrays in GrADS.

Download Array Example Script

   


4 comments:

  1. Hey
    I want to calculate the accumulated burden. What I want is that at any time the value of accumulated burden is the sum of emission in the previous time steps.
    I wrote something like this
    i=2
    'set t 1'
    'd FEMIS-FDEPOS'
    FACC.1=subwrd(result,4)
    while(i<=169)
    'set t 'i
    j=i-1
    'd FEMIS-FDEPOS'
    FACC.i=FACC.j + subwrd(result,4)
    i=i+1
    endwhile
    'set t 1 last'
    'd FACC'
    'd FBURDEN'

    So how can I display the whole array to make a line plot?

    ReplyDelete
  2. So, there may be a better way to do this than using arrays they way they are being used here. When you 'set gxout print' and store the result of that into an array, you are effectively just saving a number into a location, and thus if you try to "display" your array using GrADS syntax, it won't work. I did put together a script called "scatter.gs" which will create line plots using arrays built this way (though you would have to set a variable to represent time to fit the x-axis).

    However, I think it might be better to skip arrays all together and simply do it using the 'define' command.

    I'm not sure what your variables are, but to get the sum of a variable for the previous to time steps, something like this works okay:

    'set t 3 'timemax
    'burden = sum(emission,t-2,t)'

    'd burden'

    I'm not sure if this is the exact syntax, but I think something like this should work. If not, try scatter.gs using an x-axis to fit the time-series.

    Hope this helps!


    ReplyDelete
  3. HEY
    I am here to bother you once again. I want to read a binary file and write the result(temperature tendency) in ascii file. The binary data is temperature observed at a given station from radiosonde data.
    Here is the code that I used.
    'reinit'
    'open sonde_bbm_plevs_v4_newvars.ctl'
    outfile='BBM_sonde_temp_tend.txt'
    j=1
    loop through the vertical levels
    while(j<837)
    'set z 'j
    i=1
    *loop through time
    while(i<547)
    'set t 'i
    'd (tmp(t='i+6')-tmp(t='i'))*4'
    ttend.j.i=subwrd(result,4)
    i=i+6
    endwhile
    j=j+1
    endwhile
    'set gxout print'
    'set prnopts %7.4f 1 1'
    i=1
    while(i<553)
    'set t 'i
    'q time'
    TTT=subwrd(result,3)
    write(outfile,TTT,append)
    j=1
    *write temperature tendency at a particular time for the whole p-level
    while(j<837)
    'set z 'j
    'd lev'
    levl=subwrd(result,4)
    'd 'ttend.j.i
    tem_tend=sublin(result,2)
    rc=write(outfile,temp_tend,append)
    j=j+1
    endwhile
    i=i+6
    endwhile

    ReplyDelete
  4. loop through vertical levels is commented

    ReplyDelete