TimesUpdateNoData.c 11.9 KB
/**
*  @file TimesUpdateNoData.c
*  @version $Id: TimesUpdateNoData.c,v 1.6 2009/07/07 11:37:40 budnik Exp $
*  @brief Program reads StartTime and StopTime and add to nc_times_file NODATA intervals
*  
*  @arg  nc_times_file OrderedStartTime OrderedStopTime
*/

/*=====================================================================
 *                  DD SYSTEM base package
 *                   DD_Server library
 *                    TimesUpdateNoData.c
 *                        V.1.5
 *
 *  usage TimesUpdateNoData  nc_times_file OrderedStartTime OrderedStopTime
 *   
 *=====================================================================*/
 /*=====================================================================
 * Description:
 * Program reads StartTime and StopTime and add to nc_times_file NODATA intervals 
 *  
 * 
 *
 * Dimensions:
 * TimeLingth   TIMELENGTH
 * NameLength   NAME_DIM
 * Record       Unlimited
 * Variables:
 *
 * char StartTime[TIMELENGTH]
 * char EndTime[TIMELENGTH]
 * 
 * Attributes:
 * none
 *======================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>
#include <netcdf.h>
#include <math.h>
#include <DD.h>
 

/* Global Constant definitions */
#define ISOTIMER  "%d-%d-%dT%d:%d:%d.%dZ" /* Format to READ time in ISO format */ 
#define TIME_LENGTH_NAME "TimeLength"
#define TIME_LENGTH 17L
#define REC_DIM_NAME "record"
#define REC_DIM NC_UNLIMITED
#define NAME_DIM_NAME "NameLength"
#define NAME_DIM 32L
#define NAME_LENGTH 100
#define ISO_LENGTH 25

#define STARTTIME "StartTime"
#define STOPTIME   "StopTime"
#define FILENAME   "FileName"

#define TIME_TYPE NC_CHAR


#define DATAGAP 7200
#define NODATA "NODATA\0"

 
/*----------- Type definition ------------------------------*/
typedef struct
{
   char Name[NAME_LENGTH];   // current data file 
   char StartS[TIME_LENGTH]; // Start Time String
   char StopS[TIME_LENGTH];  // Stop Time String
  
   double StartD;            // Start double
   double StopD;             // Stop double 
} t_StartStop;

/*---------- Global variables (IDs) of open times file -------------*/
   int tmID;  /* nc file descriptor */
   int StartID, StopID, NameID;
   size_t RecordsNumber = 0; // Records Number of the existing times file
   static char ZeroTime[TIME_LENGTH] = "0000000000000000\0";
   

/*========================================================================
 *                 FUNCTIONS 
 *=======================================================================*/
/*=====================================================================
 *                ISOTime2Double()
 * Covert double time to ISO time to Double
 *  
 *=====================================================================*/
double ISOTime2Double(char* ISO)
{
  unsigned UT[7];
  dd_tmstr_t *Time;
  sscanf(ISO, ISOTIMER, &UT[0], &UT[1], &UT[2], &UT[3], &UT[4], &UT[5], &UT[6]);
  Time = (dd_tmstr_t *)UT2double(UT);
  return Time->times;
}

/*-----------------------------------------------------------*/

/*------------------------------------------------------------
 *                 InsertRecord()
 *-----------------------------------------------------------*/
int InsertRecord(size_t RecordPos, t_StartStop *StartStop)
{
   static size_t TimeStart[2] = {0,0};
   static size_t TimeCount[2] = {1,TIME_LENGTH};
   static size_t NameCount[2] = {1, NAME_DIM};
   char CStart[TIME_LENGTH],CStop[TIME_LENGTH], CName[NAME_DIM];
   int Crec;
   int status;

/*--- Scroll all variables down-----------------------*/   
   for(Crec = RecordsNumber - 1; Crec >= (int)RecordPos; Crec--)
   {
       TimeStart[0] =  (size_t)Crec;
       status = nc_get_vara_text (tmID,StartID,TimeStart,TimeCount,(char *)CStart);
       status = nc_get_vara_text (tmID,StopID,TimeStart,TimeCount,(char *)CStop);
       status = nc_get_vara_text (tmID,NameID,TimeStart,NameCount,(char *)CName);
       TimeStart[0]++;
       status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)CStart);
       status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)CStop);
       status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)CName);
   }

/*------ Put the new record to empty space  -----------------*/
   TimeStart[0] = RecordPos;
   status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)StartStop->StartS);
   status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)StartStop->StopS);
   status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)StartStop->Name);
  
   RecordsNumber++;
   nc_sync(tmID);
   return 1;
}
/*==================================================================================*/

/*==================================================================================
 *                              MAIN
 *==================================================================================*/
main(int argc, char **argv)
{
   static char usage[] = "usage: TimesUpdateNoData  nc_times_file StartTime StopTime";

   char Start[TIME_LENGTH], Stop[TIME_LENGTH], Name[NAME_DIM];

/* NC definitions */
   int TlDimID,RecDimID, NlDimID;  /* ID of dimensions */
   
   static size_t TimeStart[2] = {0,0};
   static size_t TimeCount[2] = {1,TIME_LENGTH};
   static size_t NameCount[2] = {1, NAME_DIM};

   int DimVector[2];

   char tmName[NAME_DIM];
   int InsertFlag;
 
   int i, hi, lo = 0;  
   double StartD0, StartD1 = 0.0, StopD0, StopD1, STARTD, STOPD, CurrentStart; 
   int StartRecord, StopRecord;

   char command[100];
   char name[100];
   
   int status;
   
   double LastTime = 0.0, FirstTime = 0.0; // Times of the hole between files
      
   t_StartStop CurrentRecord; //  
 

/*=================================================================
 * Check arguments and options
 *=================================================================*/
   if(argc < 4)  {fprintf(stderr,"%s\n",usage); exit(1); }
   
/*-----------------------------------------------------------------*/
   
    
        /* Open existing file */
         if((status = nc_open(argv[1],NC_WRITE|NC_SHARE,&tmID)) != NC_NOERR)
         {
            fprintf(stderr,"Can not open file %s to write\n",argv[2]);
            exit(0);
         }
         status = nc_inq_dimid(tmID,REC_DIM_NAME,&RecDimID);
         status = nc_inq_varid(tmID, STARTTIME,&StartID);
         status = nc_inq_varid(tmID, STOPTIME,&StopID);
         status = nc_inq_varid(tmID, FILENAME,&NameID);
         status = nc_inq_dimlen(tmID,RecDimID, &RecordsNumber);
   
/*==========================================================================*/
  
      hi = RecordsNumber;
 
       STARTD = ISOTime2Double(argv[2]);
       STOPD = ISOTime2Double(argv[3]);
 
     while (lo <=  hi)
       {               
               i = (lo+hi)/2; 
               TimeStart[0] = i + 1;
               status = nc_get_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)Start);
               StartD1 = DD_Time2Double(Start);
               if (StartD1 > STARTD) hi--;  
               TimeStart[0] = i;
               status = nc_get_vara_text(tmID,StartID,TimeStart,TimeCount,(char *)Start);
               StartD0 = DD_Time2Double(Start);                
               if (StartD0 < STARTD) lo++;

               if (StartD1 <=  STARTD && StartD0 >= STARTD) break;
       }  

       StartRecord = i;
       status = nc_get_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)Stop);
       StopD0 = DD_Time2Double(Stop);

       while (STOPD > StopD0  &&  TimeStart[0] <= RecordsNumber) {
              status = nc_get_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)Stop);
              if (status != NC_NOERR) fprintf(stderr," %s\n", nc_strerror(status));
              StopD0 = DD_Time2Double(Stop);
              TimeStart[0]++;
        }

       StopRecord = TimeStart[0]-1;

// if NODATA is the very FIRST - insert NODATA 
       if (StartRecord == 0  && (StartD0 - STARTD) > DATAGAP) {
        
           TimeStart[0] = 0;
           status = nc_get_vara_text(tmID, NameID, TimeStart, NameCount,(char *)Name); 
           if (strcmp(Name,NODATA) == 0 && (StartD0 - STOPD) < DATAGAP) {
             status = nc_put_vara_text(tmID,StartID, TimeStart, TimeCount, Double2DD_Time(STARTD));          
           }
          else  {
              strncpy(CurrentRecord.Name, NODATA, 7);  
              strncpy(CurrentRecord.StartS,Double2DD_Time(STARTD),TIMELENGTH);
              if ((StartD0 - STOPD)  < DATAGAP) strncpy(CurrentRecord.StopS,Start,TIMELENGTH); 
                else strncpy(CurrentRecord.StopS,Double2DD_Time(STOPD),TIMELENGTH);
              InsertRecord((size_t)(0), &CurrentRecord);
          }          
       }
     
        for (i = StartRecord; i < StopRecord ; i++) {

         InsertFlag = 0;
         TimeStart[0] = i;
         status = nc_get_vara_text(tmID,StopID, TimeStart, TimeCount,(char *)Stop); 
         StopD0 = DD_Time2Double(Stop);
         TimeStart[0] = i+1; 
         status = nc_get_vara_text(tmID,StartID, TimeStart, TimeCount, (char *)Start);
         StartD1 = DD_Time2Double(Start);
     

// Data Gap -> NODATA
 
         if ((StartD1 - StopD0) > DATAGAP)  {
           strncpy(CurrentRecord.Name, NODATA,7);

           TimeStart[0] = i;
           status = nc_get_vara_text(tmID, NameID, TimeStart, NameCount,(char *)Name);     
 
           if (strcmp(Name,NODATA) == 0) {
                   strncpy(Stop,Start,TIMELENGTH);
                   status = nc_get_vara_text(tmID,StartID, TimeStart, TimeCount, (char *)Start);
                   status = nc_put_vara_text(tmID,StartID, TimeStart, TimeCount, (char *)Start);
                   if ((StartD1 - STOPD) <  DATAGAP)
                           status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,(char *)Stop);
                   else status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount,Double2DD_Time(STOPD));
                   status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)CurrentRecord.Name);
  
                   InsertFlag = 1;
           }

            if (!InsertFlag) {
                  if ((i == StartRecord) && (StopD0 < STARTD))
                            strncpy(CurrentRecord.StartS,Double2DD_Time(STARTD),TIMELENGTH);
                  else strncpy(CurrentRecord.StartS,Stop,TIMELENGTH);
                  if ((i == StopRecord-1) && (StartD1 > STOPD))  
                            strncpy(CurrentRecord.StopS,Double2DD_Time(STOPD),TIMELENGTH);
                  else strncpy(CurrentRecord.StopS,Start,TIMELENGTH);
                 
                 if ((DD_Time2Double(CurrentRecord.StopS) - 
                                     DD_Time2Double(CurrentRecord.StartS)) > DATAGAP)
                                           InsertRecord((size_t)(i+1), &CurrentRecord);

            }       
         }

      }
     
// if NODATA is the very LAST - add NODATA
 
    if (StopRecord == RecordsNumber) {
         TimeStart[0] = StopRecord-1;
         status = nc_get_vara_text(tmID,StopID, TimeStart, TimeCount, (char *)Stop);
         StopD0 = DD_Time2Double(Stop);

         if (STOPD > StopD0) { 
           status = nc_get_vara_text(tmID, NameID, TimeStart, NameCount,(char *)Name);  
 
          if (strcmp(Name,NODATA) == 0  && (STARTD - StopD0) < DATAGAP) {
              status = nc_get_vara_text(tmID,StartID, TimeStart, TimeCount, (char *)Start);
              strncpy(Stop,Start,TIMELENGTH);
          }
          else  {
               strncpy(Name, NODATA, 7); 
               TimeStart[0]++;
          }   
         if ((STARTD - StopD0) < DATAGAP) CurrentStart = DD_Time2Double(Stop); 
         else   CurrentStart = STARTD; 
         if ((STOPD - CurrentStart) > DATAGAP) {
            status = nc_put_vara_text(tmID,StartID,TimeStart,TimeCount, Double2DD_Time(CurrentStart));
            status = nc_put_vara_text(tmID,StopID,TimeStart,TimeCount, Double2DD_Time(STOPD));
            status = nc_put_vara_text(tmID,NameID,TimeStart,NameCount,(char *)Name);
        }
      }   
    }

 
   nc_sync(tmID);
   status = nc_close(tmID);
   exit(0);
} 
/*=========================================================================================================*/