RAVE
|
On the previous page, we gave a brief overview on how you are supposed to work with the different support macros and functions we have delivered in the system.
Let's take a look at some of the objects we have at our disposal.
#include "rave_datetime.h" static void somefun(void) { RaveDateTime_t* datetime = RAVE_OBJECT_NEW(&RaveDateTime_TYPE); if (datetime != NULL) { RaveDateTime_setDate(datetime, "20091010"); RaveDateTime_setTime(datetime, "100000"); } ... RAVE_OBJECT_RELEASE(datetime); }What happens if you specify a badly-formatted date or time, or any other oddity? Try for yourself by checking the return value from RaveDateTime_setDate and RaveDateTime_setTime ... or you could read the documentation.
#include "rave_data2d.h" static void somefun(void) { RaveData2D_t* data = RAVE_OBJECT_NEW(&RaveData2D_TYPE); if (data != NULL) { if (RaveData2D_createData(data, 10, 10, RaveDataType_UCHAR)) { RaveData2D_setValue(data, 2, 2, 10.0); } } RAVE_OBJECT_RELEASE(data); }All setting and getting of data is actually done as doubles and the casting is done inside the functions. So, if you pass in a double that is > 255 into the above call, then the value in the data array will be set to 255.
#include "raveobject_list.h" static void somefun(RaveObjectList_t* list) { int len = RaveObjectList_size(list); int i = 0; for (i = 0; i < len; i++) { RaveCoreObject* object = RaveObjectList_get(list, i); .... RAVE_OBJECT_RELEASE(object); } }Currently, we only support size and indexing, but eventually we are going to introduce an iterator as well.
#include "rave_list.h" static void somefun(void) { RaveList_t* list = RAVE_OBJECT_NEW(&RaveList_TYPE); ... RaveList_add(list, ptr); ... while ((ptr = RaveList_removeLast(list)) != NULL) { RAVE_FREE(ptr); } RAVE_OBJECT_RELEASE(list); }
That's the basic objects that only are there for making life a bit easier. We have a number of objects that are more interesting when working with radar data (or any other data) for that matter.
#include "projection.h" static void somefun(void) { Projection_t* p1 = RAVE_OBJECT_NEW(&Projection_TYPE); Projection_t* p2 = RAVE_OBJECT_NEW(&Projection_TYPE); double x = 0.0L, y = 0.0L; if (!Projection_init(p1, "stere", "my projection", "+proj=stere +ellps=bessel +lat_0=90 +lon_0=14 +lat_ts=60 +datum=WGS84")) { goto error; } if (!Projection_init(p2, "lonlat", "another projection description", "+proj=longlat +ellps=WGS84 +datum=WGS84")) { goto error; } x = 60.0 * M_PI/180.0; y = 14.0 * M_PI/180.0; if (!Projection_transform(p2, p1, &x, &y, NULL)) { goto error; } fprintf(stderr, "Surface coordinates %f, %d\n", x, y); error: RAVE_OBJECT_RELEASE(p1); RAVE_OBJECT_RELEASE(p2); }This code shows how you are able to translate a lon/lat coordinate into a surface coordinate represented by the stereographic projection p1. The most interesting function in this class is Projection_transform that will ensure that datum changes will be performed as long as +datum= has been specified. For further information on the usage, please refer to PROJ.4 documentation.
Currently we have three different products that define the basic needs when working with radar data. Instead of writing some examples on how these are used, a list of the other objects will be presented below and at the end a simple main program that creates a PPI will be shown.
Other than that we have a couple of utilities that are useful when working with the objects defined above.
/** * Simple PPI generator example without any checks or controls. */ #include "rave_io.h" #include "polarscan.h" #include "cartesian.h" #include "polarvolume.h" #include "area.h" /** * Arguments are: <filename> <scan index> <areaid> int main(int argc, char** argv) { RaveIO_t* raveio = RaveIO_open(argv[1]); PolarScan_t* scan = NULL; Cartesian_t* result = NULL; Area_t* area = NULL; if (RaveIO_getObjectType(raveio) == Rave_ObjectType_PVOL) { PolarVolume_t* volume = RaveIO_getObject(raveio); scan = PolarVolume_getScan(volume, atoi(argv[2])); RAVE_OBJECT_RELEASE(volume); } area = createArea(argv[3]); result = createPPI(scan, area); raveio.setFilename("result.h5") raveio.setObject(result); raveio.save(); RAVE_OBJECT_RELEASE(raveio); RAVE_OBJECT_RELEASE(scan); RAVE_OBJECT_RELEASE(area); return 0; }
The above example may leave a couple of unanswered questions, but at least it shows how the system can be used. For example, the object Transform_t supports ppi/cappi/pcappi when writing this documentation but this might change in the future and hence, I leave it up to the reader of this document to check what APIs you have at your disposal.
We have covered the basics and some of the building blocks and now it is time to take a look at a real-life example that was performed when developing the new version of RAVE, A real-life example on converting existing averaging filter functionality. This example provides a complete example of writing a C module and a Python wrapper for it.