/****************************************************************************/ /* */ /* IL_index.h */ /* */ /****************************************************************************/ /****************************************************************************/ /* This is a C language header file that defines the following routine for */ /* reading IL index data file into memory. */ /* */ /* ------------------ Read data from an IL index data file ----------- */ /* */ /* long ReadIL(char *FileName,NetworkPtr Network,char *StartTimeStr, */ /* char *EndTimeStr) */ /* FileName Name of the IL-file containing the data. */ /* Contrary to other format reading routines ReadIL */ /* cannot read data from stdin. Therefore FileName */ /* must not be nil nor zero length. */ /* Network Structure into which the data is read. */ /* Network_struct is defined in file MagnData.h. */ /* StartTimeStr String defining the first time to be read from */ /* the data file (String delimited with '\0'). */ /* String format : YYMMDDHH. If HH is missing then */ /* 00 is assumed. If StartTimeStr is nil or zero */ /* length then start of file is assumed. */ /* EndTimeStr String defining the time not to be read anymore. */ /* Format as before YYMMDDHH. If nil or zero length */ /* then data is read until end of file. */ /* */ /* The function result indicates how successfull the file reading was: */ /* 0: OK : File read successfully */ /* 1: FileError : Failed to read the given file */ /* 2: OutOfMemory : Memory allocation failed during reading */ /* 3: FormatError : File to be read is not a IL file */ /* */ /****************************************************************************/ /****************************************************************************/ /* Lasse Hakkinen */ /* Finnish Meteorological Institute */ /* Department of Geophysics */ /* P.O.Box 503 */ /* FIN-00101, Helsinki, Finland */ /* e-mail: Lasse.Hakkinen@fmi.fi */ /* phone : (+358)-9-19294634 */ /* fax : (+358)-9-19294634 */ /* */ /* version 1.01 15.05.2019 */ /****************************************************************************/ /****************************************************************************/ /* Version history: */ /* */ /* 1.01 15.05.2019 Added header format 1 and 2 reading */ /* 1.0 18.09.2006 First official release */ /****************************************************************************/ #include #include #include #define MissingIL 999999 #define Column_IL 22 #define Column_IU 30 #define Column_IE 38 #define Column_SS 50 static long LineNbr = 0; /* Current line number */ static long Station_Statistic = 0; /* Flag for indicating if the data */ /* file contains station statistics */ /*--------------------------------------------------------------------------*/ /* Function prototypes */ /*--------------------------------------------------------------------------*/ static Time_sec GetILTime(char *Line); static int ReadILLine(FILE *ILfile,char *Line); static void SetStationParamsIL(StationPtr Station,Time_sec T); static long Get4charValue(char *p); static long GetILFieldValue(char *p); static void GetILData(StationPtr Station, char *Buff, Time_sec CurrTime); long ReadIL(char *FileName, NetworkPtr Network, char *StartTimeStr, char *EndTimeStr, char *StationsStr, char *BaselinesStr, char *IUstatisticsStr, char *ILstatisticsStr); /*==========================================================================*/ /* Routines for reading IL index data file */ /*==========================================================================*/ /*--------------------------------------------------------------------------*/ /* Get the time of the current data line (in seconds). */ /*--------------------------------------------------------------------------*/ static Time_sec GetILTime(char *Line) { char DateStr[20]; strncpy(DateStr ,Line+2,2); strncpy(DateStr+2 ,Line+5,2); strncpy(DateStr+4 ,Line+8,2); strncpy(DateStr+6 ,Line+11,2); strncpy(DateStr+8 ,Line+14,2); strncpy(DateStr+10,Line+17,2); DateStr[12] = 0; /* String terminator */ return (StrToSecs(DateStr,12)); } /*--------------------------------------------------------------------------*/ /* Read one line from the IL index data file into the Buffer. */ /* The routine will return 1 if the line was read succesfully , otherwise */ /* 0 is returned. */ /*--------------------------------------------------------------------------*/ int ReadILLine(FILE *ILfile,char *Line) { int c; while (((c = getc(ILfile)) != EOF) && (c > 31)) { *Line++ = c; } *Line++ = '\0'; /* zero byte */ LineNbr++; if (c != EOF) return(1); else return(0); } /*--------------------------------------------------------------------------*/ /* Fill some fields in the Station_struct. */ /*--------------------------------------------------------------------------*/ static void SetStationParamsIL(StationPtr Station,Time_sec T) { StationInfoPtr StationInfo; /* Set the station ID */ strcpy(Station->StationID,"IL_"); /* Set the location of the station */ Station->Latitude = 9000; Station->Longitude = 0; /* Set the component markers */ strcpy(Station->Components,"XYZ"); /* Set the start time. End time is updated by GetILData routine */ Station->StartTime = T; } /*--------------------------------------------------------------------------*/ /* Get the 4 character number from the Buffer. We could also use sscanf, */ /* but this is considerably faster because no checkings are made. */ /*--------------------------------------------------------------------------*/ static long Get4charValue(char *p) { int k; long value = 0; while (*p == ' ') p++; /* scan leading zeros */ /* Get the 4 characters */ for (k=0;k<4;k++) { if (*p != ' ') value = 10*value+(*p-'0'); p++; } return (value); } /*--------------------------------------------------------------------------*/ /* Get the 6.1 character number from the Buffer. We could also use sscanf, */ /* but this is considerably faster because no checkings are made. */ /*--------------------------------------------------------------------------*/ static long GetILFieldValue(char *p) { long value = 0; long negative = 0; while (*p == ' ') p++; /* scan leading zeros */ if (*p == '-') { /* get the sign */ negative = 1; p++; } while (*p != '.') { /* get the integer part */ value = 10*value+(*p-'0'); p++; } p++; value = 10*value+(*p-'0'); /* get the decimal part */ if (negative) value = -value; if (value >= MissingIL) value = MissingValue; return (value); } /*--------------------------------------------------------------------------*/ /* Copy data from a single data line into proper OneDayBlock. */ /*--------------------------------------------------------------------------*/ static void GetILData(StationPtr Station, char *Line, Time_sec CurrTime) { OneDay_struct *p; long *XPtr,*YPtr,*ZPtr,*TPtr,*FPtr; /* Find the last OneDayBlock */ for (p = Station->FirstDay; p->NextDay != NULL; p = p->NextDay); /* Set the temperature value */ TPtr = (p->T)+(p->TCount); *TPtr = MissingValue; p->TCount++; /* Set the pointers within the OneDayBlock */ XPtr = (p->X)+(p->XCount); YPtr = (p->Y)+(p->YCount); ZPtr = (p->Z)+(p->ZCount); if (Station_Statistic) FPtr = (p->F)+(p->ZCount); /* Copy the data */ *XPtr = GetILFieldValue(Line+Column_IL); *YPtr = GetILFieldValue(Line+Column_IU); *ZPtr = GetILFieldValue(Line+Column_IE); if (Station_Statistic) *FPtr = Get4charValue(Line+Column_SS); p->XCount++; p->YCount++; p->ZCount++; /* Update the end time */ Station->EndTime = CurrTime+Station->TimeStep; } /*--------------------------------------------------------------------------*/ /* Here is the routine for reading IL index data file into memory. */ /* The data is read into a Network structure (see MagnData.h for details). */ /* See the comments at the beginning of this file for more details about */ /* the parameters for this routine. */ /*--------------------------------------------------------------------------*/ long ReadIL(char *FileName, NetworkPtr Network, char *StartTimeStr, char *EndTimeStr, char *StationsStr, char *BaselinesStr, char *IUstatisticsStr, char *ILstatisticsStr) { FILE *ILfile; /* The data file to be processed */ char Buffer[500]; /* Buffer for one IL data line */ Time_sec Time; /* Time of the current data block */ Time_sec OldTime; /* Time of the previous data block */ Time_sec StartTime; /* Time of first record to be read */ Time_sec EndTime; /* Time of record not read anymore */ Time_sec TimeStep; /* Sampling rate in the IL file */ StationPtr Station = NULL; /* Pointer to the current station */ long FirstLine = 1; /* Flag for first valid data line */ InitNetwork(Network); /* Initialize the fields of Network */ /* --- Set the start and end times --- */ if ((StartTimeStr == NULL) || (*StartTimeStr == '\0')) StartTime = MIN_TIME; else StartTime = StrToSecs(StartTimeStr,0); if ((EndTimeStr == NULL) || (*EndTimeStr == '\0')) EndTime = MAX_TIME; else EndTime = StrToSecs(EndTimeStr,0); /* --- Try to open the file --- */ if ((ILfile = fopen(FileName, "r")) == NULL) return FileError; /* --- Find the station ID's and baseline values --- */ ReadILLine(ILfile,Buffer); while (strncmp(Buffer+2,"The following",13) != 0) { ReadILLine(ILfile,Buffer); } ReadILLine(ILfile,Buffer); /* Station ID's */ strcpy(StationsStr,Buffer+2); ReadILLine(ILfile,Buffer); if (strncmp(Buffer+2,"Station contributions",21) == 0) { ReadILLine(ILfile,Buffer); } strcpy(IUstatisticsStr,Buffer+2); /* IU statistics */ ReadILLine(ILfile,Buffer); /* IL statistics */ strcpy(ILstatisticsStr,Buffer+2); ReadILLine(ILfile,Buffer); if (strncmp(Buffer+2,"Station baseline",16) == 0) { ReadILLine(ILfile,Buffer); } strcpy(BaselinesStr,Buffer+2); /* Baselines */ /* --- Find the sampling step in the data file --- */ ReadILLine(ILfile,Buffer); while (strncmp(Buffer+2,"File created",12) != 0) { ReadILLine(ILfile,Buffer); } ReadILLine(ILfile,Buffer); /* empty line */ ReadILLine(ILfile,Buffer); /* First data line */ if (strlen(Buffer) > Column_SS) Station_Statistic = 1; Time = GetILTime(Buffer); ReadILLine(ILfile,Buffer); TimeStep = GetILTime(Buffer) - Time; rewind(ILfile); Station = AddNewStation(Network,TimeStep,TimeStep); /* --- Read the data into one day blocks ---*/ while (ReadILLine(ILfile,Buffer)) { if ((strlen(Buffer) == 0) || (*Buffer == '%')) continue; Time = GetILTime(Buffer); if (Time >= EndTime) break; if (Time >= StartTime) { if (FirstLine) { SetStationParamsIL(Station,Time); FirstLine = 0; } if (OneDayFull(Station,'Z')) { if (AddOneDay(Station)) return(OutOfMemory); /* Failed to allocate memory */ } GetILData(Station,Buffer,Time); } } fclose(ILfile); /* --- Combine one day blocks into one large block ---*/ if (CombineData(Station) == OutOfMemory) return(OutOfMemory); return OK; }