# The GrADS- Python Interface (GradsPy)

GrADS version 2.2.1 introduces a new C-language Python extension, called GradsPy. The interface has a few components: a C program called gradspy.c, a python script called setup.py, and a build of GrADS that is compiled as a dynamically loading library, called libgradspy.so (or libgradspy.dylib). The libgradspy.* files are generated along with the regular binary executables when compiling GrADS.

## Installing GradsPy

1. Move to the directory where your GrADS source code is installed (e.g. $HOME/grads-2.2.1/src). Make sure that gradspy.c, gradspy.h, and setup.py are in that directory. Edit the gradspy.c file so that the dlopen command will point to the correct name of the libgradspy file for your system (use the .so extension for linux, the .dylib extension for Mac OS X). The relevant code looks like this (you must comment out one of these):

`handle = dlopen ("libgradspy.so", RTLD_LAZY | RTLD_GLOBAL ); /* for linux */
handle = dlopen ("libgradspy.dylib", RTLD_LAZY | RTLD_GLOBAL ); /* for mac */`

2. Now you are ready to compile gradspy.c with the following command:
`> python setup.py install`

Be sure you are using Python version 2, we haven't done any testing with Python 3. You must also have NumPy installed on your system, because the GradsPy extension delivers NumPy objects when evaluting expressions. Use 'sudo' in front of this command if you have root access privileges on your system.
3. Now you are ready to run Python and issue the command:
`>>> import gradspy`

Before you do this, make sure that your shell environment will know where to find the libgradspy.so (or libgradspy.dylib) file that GradsPy will try to open. Update the environment variable LD_LIBRARY_PATH to include the path to your grads-2.2.1 installation (e.g. $HOME/grads-2.2.1/lib).

## GradsPy Methods

Once you have imported GradsPy into Python, there are three methods for interacting with GrADS: start, cmd, and result.

### start

The 'start' method only needs to be issued once, it starts GrADS with any number of optional switches and arguments. Most space-delimited arguments to GrADS become comma-delimited and quoted arguments to the gradspy.start method. The exception to this rule is when you are using the -c argument and the script name you provide takes arguments. In this case, you would invoke the script name and its arguments inside one set of quotes. For example:
`gradspy.start()
gradspy.start("-lb")
gradspy.start("-lc","open /data/samples/model.ctl")
gradspy.start("-a","1.0","-g","800x800+60+0","-d","X11")
gradspy.start("-lb","-c","scriptname.gs arg1 arg2")`

### cmd

The 'cmd' method is how you issue any GrADS command. For example:
`gradspy.cmd('q config')`

The text that GrADS delivers to the command window (or the internal variable 'result' in a script) is also returned to Python when the cmd method is called. Python will print this unformatted text to your command window. A more elegant strategy is to assign the returned text to a local variable and save it for further parsing or better formatted printing:
`a=gradspy.cmd('q file')
print (a)`
`b=gradspy.cmd('q dims')
print (b)`

### result

The 'result' method evaluates a user-provided GrADS expression and returns the resulting grid of data and relevant metadata in a Python tuple.
`rt=gradspy.result('ave(tsfc,t=1,t=12)')`

The returned tuple (here named '`rt`' for illustration purposes) has seven elements (one integer followed by six PyObjects):

[0] The return code. If the return code is negative, then an error occurred. Otherwise, it contains the number of varying dimensions (rank) in the result grid.
[1] A 2-D NumPy array that contains the grid of data from the expression evaluation (with NaN for missing data values)
[2] A 1-D NumPy array of longitude coordinate values (NaN if X is not varying)
[3] A 1-D NumPy array of latitude coordinate values (NaN if Y is not varying)
[4] A 1-D NumPy array of level coordinate values (NaN if Z is not varying)
[5] A 1-D NumPy array of additional grid metadata containing 14 integers, listed below.

`0. X (lon) size (1 if X is not varying)
1. Y (lat) size (1 if Y is not varying)
2. Z (lev) size (1 if Z is not varying)
3. T (time) size (1 if T is not varying)
4. E (ens) size (1 if E is not varying)
5. T start time -- year
6. T start time -- month
7. T start time -- day
8. T start time -- hour
9. T start time -- minute
10. T increment
11. Type of T increment (0==months, 1==minutes)
12. T calendar type (0==normal, 1==365-day)
13. E start (E increment is always 1)`

[6] A 1-D NumPy array of additional grid metadata containing 6 doubles, listed below:

`` `0. X start value (if X dimension is linear)
1. X increment (negative if non-linear)
2. Y start value (if Y dimension is linear)
3. Y increment (negative if non-linear)
4. Z start value (if Z dimension is linear)
5. Z increment (negative if non-linear)`

## Usage Notes

1. When the result of an expression is a 2D lat/lon grid, GrADS orients the data with dimension 0 as i (or X, or longitude) and dimension 1 as j (or Y, or latitude). In Python, the dimension order convention is reversed, so the returned grid's dimension 0 is j/Y/latitude, and dimension 1 is i/X/longitude. This rule generalizes for all results that vary in two dimensions -- the (i,j) data array in GrADS gets sent to Python as (j,i).