Ticket 703: Add possibility to select what fields that should be included in the... jenkins-wrwp-25
authorAnders Henja <anders@henjab.se>
Thu, 16 Nov 2017 21:14:10 +0000 (22:14 +0100)
committerAnders Henja <anders@henjab.se>
Thu, 16 Nov 2017 21:14:10 +0000 (22:14 +0100)
lib/wrwp.c
lib/wrwp.h
pywrwp/baltrad_wrwp_pgf_plugin.py
pywrwp/pywrwp.c
test/pytest/WrwpTest.py

index 1e5d470..de76a3c 100644 (file)
@@ -35,6 +35,9 @@ along with HLHDF.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdio.h>
 #include <stdlib.h>
 #include "rave_attribute.h"
+#include "rave_utilities.h"
+#include "rave_datetime.h"
+
 /**
  * Represents one wrwp generator
  */
@@ -124,7 +127,7 @@ static int WrwpInternal_addDoubleAttr2Field(RaveField_t* field, const char* name
   RaveAttribute_t* attr = RaveAttributeHelp_createDouble(name, quantity);
   result = RaveField_addAttribute(field, attr);
   if (attr == NULL || !result) {
-    RAVE_ERROR0("Failed to add what/quantity attribute to field");
+    RAVE_ERROR1("Failed to add %s attribute to field", name);
     goto done;
   }
   RAVE_OBJECT_RELEASE(attr);
@@ -132,6 +135,88 @@ done:
   return result;
 }
 
+/**
+ * Returns a tokenized list (or empty) of fields that is wanted
+ * @param[in] fieldsToGenerate - the fields to generate
+ * @returns the list of wanted fields
+ */
+static RaveList_t* WrwpInternal_createFieldsList(const char* fieldsToGenerate)
+{
+  RaveList_t* result = RaveUtilities_getTrimmedTokens(fieldsToGenerate, ',');
+  if (RaveList_size(result) == 0) {
+    RaveList_add(result, RAVE_STRDUP("ff"));
+    RaveList_add(result, RAVE_STRDUP("ff_dev"));
+    RaveList_add(result, RAVE_STRDUP("dd"));
+    RaveList_add(result, RAVE_STRDUP("dbzh"));
+    RaveList_add(result, RAVE_STRDUP("dbzh_dev"));
+    RaveList_add(result, RAVE_STRDUP("nz"));
+  }
+  return result;
+}
+
+/**
+ * Returns if the specified id exist as an id in the fieldIds.
+ * @param[in] fieldIds - the list of ids
+ * @param[in] id - the id to query for
+ * @returns if the list of ids contains the specified id
+ */
+static int WrwpInternal_containsField(RaveList_t* fieldIds, const char* id)
+{
+  int i = 0, n = 0;
+  n = RaveList_size(fieldIds);
+  for (i = 0; i < n; i++) {
+    if (RaveList_get(fieldIds, i) != NULL && strcmp((char*)RaveList_get(fieldIds, i), id) == 0) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static int WrwpInternal_addNodataUndetectGainOffset(RaveField_t* field, double nodata, double undetect, double gain, double offset)
+{
+  if (!WrwpInternal_addDoubleAttr2Field(field, "what/nodata", nodata) ||
+      !WrwpInternal_addDoubleAttr2Field(field, "what/undetect", undetect) ||
+      !WrwpInternal_addDoubleAttr2Field(field, "what/gain", gain) ||
+      !WrwpInternal_addDoubleAttr2Field(field, "what/offset", offset)) {
+    return 0;
+  }
+  return 1;
+}
+
+static RaveDateTime_t* WrwpInternal_getStartDateTimeFromScan(PolarScan_t* scan)
+{
+  RaveDateTime_t* dt = RAVE_OBJECT_NEW(&RaveDateTime_TYPE);
+  RaveDateTime_t* result = NULL;
+  if (dt != NULL) {
+    if (!RaveDateTime_setDate(dt, PolarScan_getStartDate(scan)) ||
+        !RaveDateTime_setTime(dt, PolarScan_getStartTime(scan))) {
+      RAVE_WARNING0("Failed to initialize datetime object with start date/time");
+      goto done;
+    }
+  }
+  result = RAVE_OBJECT_COPY(dt);
+done:
+  RAVE_OBJECT_RELEASE(dt);
+  return result;
+}
+
+static RaveDateTime_t* WrwpInternal_getEndDateTimeFromScan(PolarScan_t* scan)
+{
+  RaveDateTime_t* dt = RAVE_OBJECT_NEW(&RaveDateTime_TYPE);
+  RaveDateTime_t* result = NULL;
+  if (dt != NULL) {
+    if (!RaveDateTime_setDate(dt, PolarScan_getEndDate(scan)) ||
+        !RaveDateTime_setTime(dt, PolarScan_getEndTime(scan))) {
+      RAVE_WARNING0("Failed to initialize datetime object with end date/time");
+      goto done;
+    }
+  }
+  result = RAVE_OBJECT_COPY(dt);
+done:
+  RAVE_OBJECT_RELEASE(dt);
+  return result;
+}
+
 /*@} End of Private functions */
 
 /*@{ Interface functions */
@@ -255,117 +340,83 @@ double Wrwp_getVMIN(Wrwp_t* self)
   return self->vmin;
 }
 
-VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
+VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj, const char* fieldsToGenerate) {
   VerticalProfile_t* result = NULL;
-  PolarScan_t* scan = NULL;
-  PolarScanParam_t* vrad = NULL;
-  PolarScanParam_t* dbz = NULL;
   PolarNavigator_t* polnav = NULL;
   int nrhs = NRHS, lda = LDA, ldb = LDB;
-  int nscans = 0, nbins = 0, nrays, nv, nz, i, iz, is, ib, ir;
-  int findEarliestTime;
-  int findLatestTime;
+  int nscans = 0, nv, nz, i, iz, is, ib, ir;
   int firstInit;
 
-  double rscale, elangle, gain, offset, nodata, undetect, val;
-  double d, h, elangleForThisScan;
+  double elangle, gain, offset, nodata, undetect, val;
+  double d, h;
   double alpha, beta, gamma, vvel, vdir, vstd, zsum, zmean, zstd;
   double centerOfLayer, u_wnd_comp, v_wnd_comp, vdir_rad;
   int ysize = 0, yindex = 0;
-  
-  const char* starttime = NULL;
-  const char* endtime = NULL;
-  const char* startdate = NULL;
-  const char* enddate = NULL;
+
   const char* product = "VP";
-  
-  const char* startTimeOfThisScan = NULL;
-  const char* endTimeOfThisScan = NULL;
-  const char* startDateOfThisScan = NULL;
-  const char* endDateOfThisScan = NULL;
-    
-  const char* starttimeFirst = NULL;
-  const char* endtimeFirst = NULL;
-  const char* startdateFirst = NULL;
-  const char* enddateFirst = NULL;
-      
-  const char* starttimeNext = NULL;
-  const char* endtimeNext = NULL;
-  const char* startdateNext = NULL;
-  const char* enddateNext = NULL;
-  
-  char* startDateTimeStrFirst = NULL;
-  char* endDateTimeStrFirst = NULL;
-  
-  char* startDateTimeStrNext = NULL;
-  char* endDateTimeStrNext = NULL;
-   
-  char starttimeArrFirst[10];
-  char endtimeArrFirst[10]; 
-  char startdateArrFirst[10];
-  char enddateArrFirst[10];  
-  char starttimeArrNext[10];
-  char endtimeArrNext[10];
-  char startdateArrNext[10];
-  char enddateArrNext[10];
-
-  char* malfuncString = NULL;
-   
+  RaveDateTime_t *firstStartDT = NULL, *lastEndDT = NULL;
+
   /* The four field below are the ones fulfilling the requirements from the user E-profiles */
-  RaveField_t *nv_field = NULL, *HGHT_field = NULL;
-  RaveField_t *UWND_field = NULL, *VWND_field = NULL;
-  
-  /* The following fields are removed from the VP but kept in the code
-     for convenience reasons, add to initialization when needed:     
-     *RaveField_t *ff_field = NULL, *ff_dev_field = NULL, *dd_field = NULL;
-      RaveField_t *dbzh_field = NULL, *dbzh_dev_field = NULL, *nz_field = NULL; */
+  RaveField_t *nv_field = NULL, *hght_field = NULL;
+  RaveField_t *uwnd_field = NULL, *vwnd_field = NULL;
+  RaveField_t *ff_field = NULL, *ff_dev_field = NULL, *dd_field = NULL;
+  RaveField_t *dbzh_field = NULL, *dbzh_dev_field = NULL, *nz_field = NULL;
+
+  RaveList_t* wantedFields = NULL;
 
   RAVE_ASSERT((self != NULL), "self == NULL");
 
-  nv_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  HGHT_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  UWND_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  VWND_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-    
-  /* Field defs kept in the code for convenience reasons, add when needed:
-  ff_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  ff_dev_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  dd_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  dbzh_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  dbzh_dev_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
-  nz_field = RAVE_OBJECT_NEW(&RaveField_TYPE); */
-
-  if (nv_field == NULL || HGHT_field == NULL || UWND_field == NULL ||
-      VWND_field == NULL) {
-    /* Removed, add when needed:ff_field == NULL || ff_dev_field == NULL || 
-       dd_field == NULL || dbzh_field == NULL || dbzh_dev_field == NULL || 
-       nz_field == NULL || */
+  wantedFields = WrwpInternal_createFieldsList(fieldsToGenerate);
+
+  if (WrwpInternal_containsField(wantedFields, "NV")) nv_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "HGHT")) hght_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "UWND")) uwnd_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "VWND")) vwnd_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "ff")) ff_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "ff_dev")) ff_dev_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "dd")) dd_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "dbzh")) dbzh_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "dbzh_dev")) dbzh_dev_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+  if (WrwpInternal_containsField(wantedFields, "nz")) nz_field = RAVE_OBJECT_NEW(&RaveField_TYPE);
+
+  if ((WrwpInternal_containsField(wantedFields, "NV") && nv_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "HGHT") && hght_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "UWND") && uwnd_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "VWND") && vwnd_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "ff") && ff_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "ff_dev") && ff_dev_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "dd") && dd_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "dbzh") && dbzh_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "dbzh_dev") && dbzh_dev_field == NULL) ||
+      (WrwpInternal_containsField(wantedFields, "nz") && nz_field == NULL))
+  {
     RAVE_ERROR0("Failed to allocate memory for the resulting vp fields");
     goto done;
   }
+
   ysize = self->hmax / self->dz;
-  if (!RaveField_createData(nv_field, 1, ysize, RaveDataType_INT) || 
-      !RaveField_createData(HGHT_field, 1, ysize, RaveDataType_DOUBLE) ||
-      !RaveField_createData(UWND_field, 1, ysize, RaveDataType_DOUBLE) ||
-      !RaveField_createData(VWND_field, 1, ysize, RaveDataType_DOUBLE)) {
-      /* Add when needed: !RaveField_createData(ff_field, 1, ysize, RaveDataType_DOUBLE) ||
-      !RaveField_createData(ff_dev_field, 1, ysize, RaveDataType_DOUBLE) ||
-      !RaveField_createData(dd_field, 1, ysize, RaveDataType_DOUBLE) ||
-      !RaveField_createData(dbzh_field, 1, ysize, RaveDataType_DOUBLE) ||
-      !RaveField_createData(dbzh_dev_field, 1, ysize, RaveDataType_DOUBLE) ||
-      !RaveField_createData(nz_field, 1, ysize, RaveDataType_INT) || */
+
+  if ((nv_field != NULL && !RaveField_createData(nv_field, 1, ysize, RaveDataType_INT)) ||
+      (hght_field != NULL && !RaveField_createData(hght_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (uwnd_field != NULL && !RaveField_createData(uwnd_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (vwnd_field != NULL && !RaveField_createData(vwnd_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (ff_field != NULL && !RaveField_createData(ff_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (ff_dev_field != NULL && !RaveField_createData(ff_dev_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (dd_field != NULL && !RaveField_createData(dd_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (dbzh_field != NULL && !RaveField_createData(dbzh_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (dbzh_dev_field != NULL && !RaveField_createData(dbzh_dev_field, 1, ysize, RaveDataType_DOUBLE)) ||
+      (nz_field != NULL && !RaveField_createData(nz_field, 1, ysize, RaveDataType_DOUBLE))) {
     RAVE_ERROR0("Failed to allocate arrays for the resulting vp fields");
     goto done;
   }
 
+
        polnav = RAVE_OBJECT_NEW(&PolarNavigator_TYPE);
        PolarNavigator_setLat0(polnav, PolarVolume_getLatitude(inobj));
        PolarNavigator_setLon0(polnav, PolarVolume_getLongitude(inobj));
        PolarNavigator_setAlt0(polnav, PolarVolume_getHeight(inobj));
            
        nscans = PolarVolume_getNumberOfScans (inobj);
-    
 
        // We use yindex for filling in the arrays even though we loop to hmax...
        yindex = 0;
@@ -393,78 +444,47 @@ VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
        become the HGHT array */
     centerOfLayer = iz + (self->dz / 2.0);
     firstInit = 0;
-    
+
     // loop over scans
-    for (is = 0; is < nscans; is++) {      
-      scan = PolarVolume_getScan(inobj, is);
-      nbins = PolarScan_getNbins(scan);
-      nrays = PolarScan_getNrays(scan);
-      rscale = PolarScan_getRscale(scan);
-      elangleForThisScan = PolarScan_getElangle(scan);
-      elangle = elangleForThisScan;
-      startTimeOfThisScan = PolarScan_getStartTime(scan);
-      endTimeOfThisScan = PolarScan_getEndTime(scan);
-      startDateOfThisScan = PolarScan_getStartDate(scan);
-      endDateOfThisScan = PolarScan_getEndDate(scan);
-      
+    for (is = 0; is < nscans; is++) {
+      char* malfuncString = NULL;
+      PolarScan_t* scan = PolarVolume_getScan(inobj, is);
+      RaveDateTime_t* startDTofThisScan = WrwpInternal_getStartDateTimeFromScan(scan);
+      RaveDateTime_t* endDTofThisScan = WrwpInternal_getEndDateTimeFromScan(scan);
+      long nbins = PolarScan_getNbins(scan);
+      long nrays = PolarScan_getNrays(scan);
+      double rscale = PolarScan_getRscale(scan);
+      double elangleForThisScan = PolarScan_getElangle(scan);
       RaveAttribute_t* malfuncattr = PolarScan_getAttribute(scan, "how/malfunc");
+      elangle = elangleForThisScan;
       if (malfuncattr != NULL) {
         RaveAttribute_getString(malfuncattr, &malfuncString); /* Set the malfuncString if attr is not NULL */
         RAVE_OBJECT_RELEASE(malfuncattr);
       }
+
       if (malfuncString == NULL || strcmp(malfuncString, "False") == 0) { /* Assuming malfuncString = NULL means no malfunc */
-                  
-        if (elangleForThisScan * RAD2DEG >= self->emin && firstInit == 0) {
+        if (elangleForThisScan * RAD2DEG >= self->emin && firstInit == 0 && iz==0) { /* We only perform the date time calc at first iz-iteration*/
           /* Initialize using the first scan and define 2 strings for the combined datetime */
-          starttimeFirst = startTimeOfThisScan;
-          endtimeFirst = endTimeOfThisScan;
-          startdateFirst = startDateOfThisScan;
-          enddateFirst = endDateOfThisScan;
+          firstStartDT = RAVE_OBJECT_COPY(startDTofThisScan);
+          lastEndDT = RAVE_OBJECT_COPY(endDTofThisScan);
           firstInit = 1;
         }
-        
-        if (elangleForThisScan * RAD2DEG >= self->emin && firstInit == 1 && is > 0) {
-          starttimeNext = startTimeOfThisScan;
-          endtimeNext = endTimeOfThisScan;
-          startdateNext = startDateOfThisScan;
-          enddateNext = endDateOfThisScan;
-
-          strcpy(starttimeArrFirst, starttimeFirst);
-          strcpy(endtimeArrFirst, endtimeFirst);
-          strcpy(startdateArrFirst, startdateFirst);
-          strcpy(enddateArrFirst, enddateFirst);
-
-          startDateTimeStrFirst = strcat(startdateArrFirst, starttimeArrFirst);
-          endDateTimeStrFirst = strcat(enddateArrFirst, endtimeArrFirst);
-
-          strcpy(starttimeArrNext, starttimeNext);
-          strcpy(endtimeArrNext, endtimeNext);
-          strcpy(startdateArrNext, startdateNext);
-          strcpy(enddateArrNext, enddateNext);
-
-          startDateTimeStrNext = strcat(startdateArrNext, starttimeArrNext);
-          endDateTimeStrNext = strcat(enddateArrNext, endtimeArrNext);
-
-          /* Find the earliest and latest datetime's and replace the initial ones
-             if they represent an earlier starttime/startdate and a later endtime/enddate */
-          findEarliestTime = strcmp(startDateTimeStrFirst, startDateTimeStrNext);
-          findLatestTime = strcmp(endDateTimeStrFirst, endDateTimeStrNext);
-
-          /* The starttime and startdate */
-          if (findEarliestTime > 0) {
-            starttimeFirst = starttimeNext;
-            startdateFirst = startdateNext;
-          }
 
-          /* The endtime and enddate */
-          if (findLatestTime < 0) {
-            endtimeFirst = endtimeNext;
-            enddateFirst = enddateNext;
-          }             
+        if (elangleForThisScan * RAD2DEG >= self->emin && firstInit == 1 && is > 0 && iz==0) {
+          if (RaveDateTime_compare(startDTofThisScan, firstStartDT) < 0) {
+            /* Start DT of this scan is before the first saved start dt, save this one instead */
+            RAVE_OBJECT_RELEASE(firstStartDT);
+            firstStartDT = RAVE_OBJECT_COPY(startDTofThisScan);
+          }
+          if (RaveDateTime_compare(endDTofThisScan, lastEndDT) > 0) {
+            /* End DT of this scan is after the last saved end dt, save this one instead */
+            RAVE_OBJECT_RELEASE(lastEndDT);
+            lastEndDT = RAVE_OBJECT_COPY(endDTofThisScan);
+          }
         }
-                     
         // radial wind scans
         if (PolarScan_hasParameter(scan, "VRAD") || PolarScan_hasParameter(scan, "VRADH")) {
+          PolarScanParam_t* vrad = NULL;
           if (PolarScan_hasParameter(scan, "VRAD")) {
             vrad = PolarScan_getParameter(scan, "VRAD");
           } else {
@@ -503,7 +523,7 @@ VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
 
         // reflectivity scans
         if (PolarScan_hasParameter(scan, "DBZH")) {
-          dbz = PolarScan_getParameter(scan, "DBZH");
+          PolarScanParam_t* dbz = PolarScan_getParameter(scan, "DBZH");
           gain = PolarScanParam_getGain(dbz);
           offset = PolarScanParam_getOffset(dbz);
           nodata = PolarScanParam_getNodata(dbz);
@@ -528,8 +548,11 @@ VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
           }
           RAVE_OBJECT_RELEASE(dbz);
         }
-        RAVE_OBJECT_RELEASE(scan);
       }
+
+      RAVE_OBJECT_RELEASE(scan);
+      RAVE_OBJECT_RELEASE(startDTofThisScan);
+      RAVE_OBJECT_RELEASE(endDTofThisScan);
     }
 
     // radial wind calculations
@@ -591,27 +614,27 @@ VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
     v_wnd_comp = vvel * sin(vdir_rad);
     
     if ((nv < NMIN) || (nz < NMIN)) {
-      /* Add when needed: RaveField_setValue(ff_field, 0, yindex, self->nodata_VP);
-      RaveField_setValue(ff_dev_field, 0, yindex, self->nodata_VP);
-      RaveField_setValue(dd_field, 0, yindex, self->nodata_VP);
-      RaveField_setValue(dbzh_field, 0, yindex, self->nodata_VP);
-      RaveField_setValue(dbzh_dev_field, 0, yindex, self->nodata_VP);
-      RaveField_setValue(nz_field, 0, yindex, 0); */
-      RaveField_setValue(nv_field, 0, yindex, 0);
-      RaveField_setValue(HGHT_field, 0, yindex,centerOfLayer);
-      RaveField_setValue(UWND_field, 0, yindex,self->nodata_VP);
-      RaveField_setValue(VWND_field, 0, yindex,self->nodata_VP);
+      if (nv_field != NULL) RaveField_setValue(nv_field, 0, yindex, 0);
+      if (hght_field != NULL) RaveField_setValue(hght_field, 0, yindex,centerOfLayer);
+      if (uwnd_field != NULL) RaveField_setValue(uwnd_field, 0, yindex,self->nodata_VP);
+      if (vwnd_field != NULL) RaveField_setValue(vwnd_field, 0, yindex,self->nodata_VP);
+      if (ff_field != NULL) RaveField_setValue(ff_field, 0, yindex, self->nodata_VP);
+      if (ff_dev_field != NULL) RaveField_setValue(ff_dev_field, 0, yindex, self->nodata_VP);
+      if (dd_field != NULL) RaveField_setValue(dd_field, 0, yindex, self->nodata_VP);
+      if (dbzh_field != NULL) RaveField_setValue(dbzh_field, 0, yindex, self->nodata_VP);
+      if (dbzh_dev_field != NULL) RaveField_setValue(dbzh_dev_field, 0, yindex, self->nodata_VP);
+      if (nz_field != NULL) RaveField_setValue(nz_field, 0, yindex, 0);
     } else {
-      /* Add wgen needed: RaveField_setValue(ff_field, 0, yindex, vvel);
-      RaveField_setValue(ff_dev_field, 0, yindex, vstd);
-      RaveField_setValue(dd_field, 0, yindex, vdir);
-      RaveField_setValue(dbzh_field, 0, yindex, zmean);
-      RaveField_setValue(dbzh_dev_field, 0, yindex, zstd);
-      RaveField_setValue(nz_field, 0, yindex, nz); */
-      RaveField_setValue(nv_field, 0, yindex, nv);
-      RaveField_setValue(HGHT_field, 0, yindex,centerOfLayer);
-      RaveField_setValue(UWND_field, 0, yindex,u_wnd_comp);
-      RaveField_setValue(VWND_field, 0, yindex,v_wnd_comp);
+      if (nv_field != NULL) RaveField_setValue(nv_field, 0, yindex, nv);
+      if (hght_field != NULL) RaveField_setValue(hght_field, 0, yindex,centerOfLayer);
+      if (uwnd_field != NULL) RaveField_setValue(uwnd_field, 0, yindex,u_wnd_comp);
+      if (vwnd_field != NULL) RaveField_setValue(vwnd_field, 0, yindex,v_wnd_comp);
+      if (ff_field != NULL) RaveField_setValue(ff_field, 0, yindex, vvel);
+      if (ff_dev_field != NULL) RaveField_setValue(ff_dev_field, 0, yindex, vstd);
+      if (dd_field != NULL) RaveField_setValue(dd_field, 0, yindex, vdir);
+      if (dbzh_field != NULL) RaveField_setValue(dbzh_field, 0, yindex, zmean);
+      if (dbzh_dev_field != NULL) RaveField_setValue(dbzh_dev_field, 0, yindex, zstd);
+      if (nz_field != NULL) RaveField_setValue(nz_field, 0, yindex, nz);
     }
 
     RAVE_FREE(A);
@@ -623,24 +646,27 @@ VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
     yindex++; /* Next interval*/
   }
 
-  /* Set values used for /dataset1/what attributes */  
-  starttime = starttimeFirst;
-  endtime = endtimeFirst;
-  startdate = startdateFirst;
-  enddate = enddateFirst;
+  if (uwnd_field) WrwpInternal_addNodataUndetectGainOffset(uwnd_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (vwnd_field) WrwpInternal_addNodataUndetectGainOffset(vwnd_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (hght_field) WrwpInternal_addNodataUndetectGainOffset(hght_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (nv_field) WrwpInternal_addNodataUndetectGainOffset(nv_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (ff_field) WrwpInternal_addNodataUndetectGainOffset(ff_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (ff_dev_field) WrwpInternal_addNodataUndetectGainOffset(ff_dev_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (dd_field) WrwpInternal_addNodataUndetectGainOffset(dd_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (dbzh_field) WrwpInternal_addNodataUndetectGainOffset(dbzh_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
+  if (dbzh_dev_field) WrwpInternal_addNodataUndetectGainOffset(dbzh_dev_field, self->nodata_VP, self->undetect_VP, self->gain_VP, self->offset_VP);
 
-  
   result = RAVE_OBJECT_NEW(&VerticalProfile_TYPE);
   if (result != NULL) {
-    if (!VerticalProfile_setUWND(result, UWND_field) ||
-        !VerticalProfile_setVWND(result, VWND_field) ||
-        !VerticalProfile_setNV(result, nv_field) ||
-        !VerticalProfile_setHGHT(result, HGHT_field)) {
-        /* Add when needed: !VerticalProfile_setFF(result, ff_field) ||
-        !VerticalProfile_setFFDev(result, ff_dev_field) ||
-        !VerticalProfile_setDD(result, dd_field) ||
-        !VerticalProfile_setDBZ(result, dbzh_field) ||
-        !VerticalProfile_setDBZDev(result, dbzh_dev_field)) */
+    if ((uwnd_field != NULL && !VerticalProfile_setUWND(result, uwnd_field)) ||
+        (vwnd_field != NULL && !VerticalProfile_setVWND(result, vwnd_field)) ||
+        (nv_field != NULL && !VerticalProfile_setNV(result, nv_field)) ||
+        (hght_field != NULL && !VerticalProfile_setHGHT(result, hght_field)) ||
+        (ff_field != NULL && !VerticalProfile_setFF(result, ff_field)) ||
+        (ff_dev_field != NULL && !VerticalProfile_setFFDev(result, ff_dev_field)) ||
+        (dd_field != NULL && !VerticalProfile_setDD(result, dd_field)) ||
+        (dbzh_field != NULL && !VerticalProfile_setDBZ(result, dbzh_field)) ||
+        (dbzh_dev_field != NULL && !VerticalProfile_setDBZDev(result, dbzh_dev_field))) {
       RAVE_ERROR0("Failed to set vertical profile fields");
       RAVE_OBJECT_RELEASE(result);
     }
@@ -659,20 +685,19 @@ VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
   
   /* Set the times and product, starttime is the starttime for the lowest elev
      endtime is the endtime for the highest elev. */
-  VerticalProfile_setStartTime(result, starttime);
-  VerticalProfile_setEndTime(result, endtime);
-  VerticalProfile_setStartDate(result, startdate);
-  VerticalProfile_setEndDate(result, enddate);
+  VerticalProfile_setStartDate(result, RaveDateTime_getDate(firstStartDT));
+  VerticalProfile_setStartTime(result, RaveDateTime_getTime(firstStartDT));
+  VerticalProfile_setEndDate(result, RaveDateTime_getDate(lastEndDT));
+  VerticalProfile_setEndTime(result, RaveDateTime_getTime(lastEndDT));
   VerticalProfile_setProduct(result, product);
    
   /* Need to filter the attribute data with respect to selected min elangle
      Below attributes satisfy reguirements from E-profile, add other when needed */
-  
   WrwpInternal_findAndAddAttribute(result, inobj, "how/highprf", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/lowprf", self->emin);
-  /*WrwpInternal_findAndAddAttribute(result, inobj, "how/pulsewidth", self->emin); */
+  WrwpInternal_findAndAddAttribute(result, inobj, "how/pulsewidth", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/wavelength", self->emin);
- /* WrwpInternal_findAndAddAttribute(result, inobj, "how/RXbandwidth", self->emin);
+  WrwpInternal_findAndAddAttribute(result, inobj, "how/RXbandwidth", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/RXlossH", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/TXlossH", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/antgainH", self->emin);
@@ -682,58 +707,28 @@ VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj) {
   WrwpInternal_findAndAddAttribute(result, inobj, "how/nomTXpower", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/radar_msg", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/radconstH", self->emin);
-  WrwpInternal_findAndAddAttribute(result, inobj, "how/radomeloss", self->emin);
+  WrwpInternal_findAndAddAttribute(result, inobj, "how/radomelossH", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/rpm", self->emin);
   WrwpInternal_findAndAddAttribute(result, inobj, "how/software", self->emin);
-  WrwpInternal_findAndAddAttribute(result, inobj, "how/system", self->emin);*/
-
+  WrwpInternal_findAndAddAttribute(result, inobj, "how/system", self->emin);
   WrwpInternal_addIntAttribute(result, "how/minrange", Wrwp_getDMIN(self));
   WrwpInternal_addIntAttribute(result, "how/maxrange", Wrwp_getDMAX(self));
-  
-  
-  /* Put in selected attributes in selected fields, currently a nodata, gain and
-     offset are defined for UWND and VWND and are put under what/nodata. */
-  WrwpInternal_addDoubleAttr2Field(UWND_field, "what/nodata", self->nodata_VP);
-  WrwpInternal_addDoubleAttr2Field(UWND_field, "what/gain", self->gain_VP);
-  WrwpInternal_addDoubleAttr2Field(UWND_field, "what/offset", self->offset_VP);
-  WrwpInternal_addDoubleAttr2Field(UWND_field, "what/undetect", self->undetect_VP);
-  
-  VerticalProfile_addField(result, UWND_field);
-  
-  WrwpInternal_addDoubleAttr2Field(VWND_field, "what/nodata", self->nodata_VP);
-  WrwpInternal_addDoubleAttr2Field(VWND_field, "what/gain", self->gain_VP);
-  WrwpInternal_addDoubleAttr2Field(VWND_field, "what/offset", self->offset_VP);
-  WrwpInternal_addDoubleAttr2Field(VWND_field, "what/undetect", self->undetect_VP);
-  
-  VerticalProfile_addField(result, VWND_field);
-  
-  WrwpInternal_addDoubleAttr2Field(HGHT_field, "what/nodata", self->nodata_VP);
-  WrwpInternal_addDoubleAttr2Field(HGHT_field, "what/gain", self->gain_VP);
-  WrwpInternal_addDoubleAttr2Field(HGHT_field, "what/offset", self->offset_VP);
-  WrwpInternal_addDoubleAttr2Field(HGHT_field, "what/undetect", self->undetect_VP);
-  
-  VerticalProfile_addField(result, HGHT_field);
-  
-  WrwpInternal_addDoubleAttr2Field(nv_field, "what/nodata", self->nodata_VP);
-  WrwpInternal_addDoubleAttr2Field(nv_field, "what/gain", self->gain_VP);
-  WrwpInternal_addDoubleAttr2Field(nv_field, "what/offset", self->offset_VP);
-  WrwpInternal_addDoubleAttr2Field(nv_field, "what/undetect", self->undetect_VP);
-  
-  VerticalProfile_addField(result, nv_field);
 
 done:
   RAVE_OBJECT_RELEASE(polnav);
-  /* 
   RAVE_OBJECT_RELEASE(ff_field);
   RAVE_OBJECT_RELEASE(ff_dev_field);
   RAVE_OBJECT_RELEASE(dd_field);
   RAVE_OBJECT_RELEASE(dbzh_field);
   RAVE_OBJECT_RELEASE(dbzh_dev_field);
-  RAVE_OBJECT_RELEASE(nz_field); */
+  RAVE_OBJECT_RELEASE(nz_field);
   RAVE_OBJECT_RELEASE(nv_field);
-  RAVE_OBJECT_RELEASE(HGHT_field);
-  RAVE_OBJECT_RELEASE(UWND_field);
-  RAVE_OBJECT_RELEASE(VWND_field);
+  RAVE_OBJECT_RELEASE(hght_field);
+  RAVE_OBJECT_RELEASE(uwnd_field);
+  RAVE_OBJECT_RELEASE(vwnd_field);
+  RAVE_OBJECT_RELEASE(firstStartDT);
+  RAVE_OBJECT_RELEASE(lastEndDT);
+  RaveList_freeAndDestroy(&wantedFields);
 
   return result;
 }
index cbfac84..e7c2a3a 100644 (file)
@@ -227,8 +227,10 @@ double Wrwp_getVMIN(Wrwp_t* self);
  * Function for deriving wind and reflectivity profiles from polar volume data
  * @param[in] self - self
  * @param[in] iobj - input volume
+ * @param[in] fieldsToGenerate - an comma-separated list of quantities. If NULL, then default
+ * behaviour is to add ff,ff_dev,dd,dbzh and dbzh_dev
  * @returns the wind profile
  */
-VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj);
+VerticalProfile_t* Wrwp_generate(Wrwp_t* self, PolarVolume_t* inobj, const char* fieldsToGenerate);
 
 #endif
index 769aebc..8326f0e 100644 (file)
@@ -21,7 +21,7 @@ along with RAVE.  If not, see <http://www.gnu.org/licenses/>.
 ## framework.
 ## Register in pgf with
 ## --name=eu.baltrad.beast.GenerateAcrr
-## --floats=minelevationangle,velocitythreshold --ints=interval,maxheight,mindistance,maxdistance -m baltrad_wrwp_pgf_plugin -f generate
+## --floats=minelevationangle,velocitythreshold --ints=interval,maxheight,mindistance,maxdistance --strings=fields -m baltrad_wrwp_pgf_plugin -f generate
 ##
 ## The WRWP generation is executed by providing a polar volume that a wind profile is calculated on
 ##
@@ -85,7 +85,7 @@ def strToNumber(sval):
 def generate(files, arguments):
   args = arglist2dict(arguments)
   wrwp = _wrwp.new()
-  
+  fields = None
   if "interval" in args.keys():
     wrwp.dz = strToNumber(args["interval"])
   if "maxheight" in args.keys():
@@ -98,6 +98,8 @@ def generate(files, arguments):
     wrwp.emin = strToNumber(args["minelevationangle"])
   if "velocitythreshold" in args.keys():
     wrwp.vmin = strToNumber(args["velocitythreshold"])
+  if "fields" in args.keys():
+    fields = args["fields"]
 
   if len(files) != 1:
     raise AttributeError, "Must call plugin with _one_ polar volume"
@@ -112,7 +114,7 @@ def generate(files, arguments):
   if not _polarvolume.isPolarVolume(obj):
     raise AttributeError, "Must call plugin with a polar volume"
 
-  profile = wrwp.generate(obj)
+  profile = wrwp.generate(obj, fields)
   
   fileno, outfile = rave_tempfile.mktemp(suffix='.h5', close="True")
   
index 4e401fb..1f789b3 100644 (file)
@@ -152,8 +152,9 @@ static PyObject* _pywrwp_generate(PyWrwp* self, PyObject* args)
        PyObject* obj = NULL;
        PyVerticalProfile* pyvp = NULL;
        VerticalProfile_t* vp = NULL;
+       char* fieldsToGenerate = NULL;
 
-       if(!PyArg_ParseTuple(args, "O",&obj)) {
+       if(!PyArg_ParseTuple(args, "O|z", &obj, &fieldsToGenerate)) {
                return NULL;
        }
 
@@ -161,7 +162,7 @@ static PyObject* _pywrwp_generate(PyWrwp* self, PyObject* args)
          raiseException_returnNULL(PyExc_AttributeError, "In argument must be a polar volume");
        }
 
-       vp = Wrwp_generate(self->wrwp, ((PyPolarVolume*)obj)->pvol);
+       vp = Wrwp_generate(self->wrwp, ((PyPolarVolume*)obj)->pvol, fieldsToGenerate);
 
        if (vp == NULL) {
          raiseException_gotoTag(done, PyExc_RuntimeError, "Failed to generate vertical profile");
index 8a09e76..332930f 100644 (file)
@@ -114,7 +114,7 @@ class WrwpTest(unittest.TestCase):
     generator.hmax = 2000
     generator.dz = 200
     
-    vp = generator.generate(pvol)
+    vp = generator.generate(pvol, "UWND,VWND,HGHT,NV")
     
     uwnd = vp.getUWND()
     vwnd = vp.getVWND()
@@ -163,7 +163,7 @@ class WrwpTest(unittest.TestCase):
     generator.hmax = 2000
     generator.dz = 200
     
-    vp = generator.generate(pvol)
+    vp = generator.generate(pvol, "UWND,VWND,HGHT,NV")
     
     uwnd = vp.getUWND()
     vwnd = vp.getVWND()
@@ -196,22 +196,22 @@ class WrwpTest(unittest.TestCase):
     
     self.assertEquals(900, vp.getAttribute("how/lowprf"))
     self.assertEquals(1200, vp.getAttribute("how/highprf"))
-    #self.assertAlmostEqual(0.61, vp.getAttribute("how/pulsewidth"), 4)
+    self.assertAlmostEqual(0.61, vp.getAttribute("how/pulsewidth"), 4)
     self.assertAlmostEqual(5.35, vp.getAttribute("how/wavelength"), 4)
-    #self.assertAlmostEqual(0.8, vp.getAttribute("how/RXbandwidth"), 4)
-    #self.assertAlmostEqual(3.1, vp.getAttribute("how/RXlossH"), 4)
-    #self.assertAlmostEqual(1.9, vp.getAttribute("how/TXlossH"), 4)
-    #self.assertAlmostEqual(44.9, vp.getAttribute("how/antgainH"), 4)
-    #self.assertEquals("AVERAGE", vp.getAttribute("how/azmethod"))
-    #self.assertEquals("AVERAGE", vp.getAttribute("how/binmethod"))
-    #self.assertEquals("False", vp.getAttribute("how/malfunc"))
-    #self.assertAlmostEqual(277.4, vp.getAttribute("how/nomTXpower"), 4)
-    #self.assertEquals("b94 3dd 000 000 000:", vp.getAttribute("how/radar_msg"), 4)
-    #self.assertAlmostEqual(73.101, vp.getAttribute("how/radconstH"), 4)
-    #self.assertAlmostEqual(0.2, vp.getAttribute("how/radomelossH"), 4)
-    #self.assertAlmostEqual(2.0, vp.getAttribute("how/rpm"), 4)
-    #self.assertEquals("PARTEC2", vp.getAttribute("how/software"))
-    #self.assertEquals("ERIC", vp.getAttribute("how/system"))
+    self.assertAlmostEqual(0.8, vp.getAttribute("how/RXbandwidth"), 4)
+    self.assertAlmostEqual(3.1, vp.getAttribute("how/RXlossH"), 4)
+    self.assertAlmostEqual(1.9, vp.getAttribute("how/TXlossH"), 4)
+    self.assertAlmostEqual(44.9, vp.getAttribute("how/antgainH"), 4)
+    self.assertEquals("AVERAGE", vp.getAttribute("how/azmethod"))
+    self.assertEquals("AVERAGE", vp.getAttribute("how/binmethod"))
+    self.assertEquals("False", vp.getAttribute("how/malfunc"))
+    self.assertAlmostEqual(277.4, vp.getAttribute("how/nomTXpower"), 4)
+    self.assertEquals("b94 3dd 000 000 000:", vp.getAttribute("how/radar_msg"), 4)
+    self.assertAlmostEqual(73.101, vp.getAttribute("how/radconstH"), 4)
+    self.assertAlmostEqual(0.2, vp.getAttribute("how/radomelossH"), 4)
+    self.assertAlmostEqual(2.0, vp.getAttribute("how/rpm"), 4)
+    self.assertEquals("PARTEC2", vp.getAttribute("how/software"))
+    self.assertEquals("ERIC", vp.getAttribute("how/system"))
     self.assertEquals(4000, vp.getAttribute("how/minrange"))
     self.assertEquals(40000, vp.getAttribute("how/maxrange"))