/****************************************************************************/ /* */ /* IAGA_extract.c */ /* */ /****************************************************************************/ /****************************************************************************/ /* This program extracts data from an IAGA-format data file. The user may */ /* give start and end times and optionally the station list. The data may */ /* may be read either from a file or from stdin. Results are written to */ /* standard output. */ /* */ /* Usage: */ /* IAGA_extract [-s] [-e | -h] [-o] [-la] [-lo] [<] IAGAFile */ /* > NewIAGAFile */ /* [-s YYYYMMDDHHMM] Time of the first record included */ /* [-e YYYYMMDDHHMM] Time of the record not included anymore */ /* [-h HH] Number of hours included */ /* [-o 'Station list'] List of stations delimited by quotes. */ /* Stations are identified by three-letter */ /* code and separated by exactly one space. */ /* e.g. 'SOR MAS KEV KIL'. */ /* If missing then all stations included. */ /* [-la LatLimits] Limits on station latitudes. 'LatLimits' is of */ /* the form MinLat-MaxLat (e.g. 45.3-62.4). Only */ /* stations within these limits are included. */ /* If -o is specified simultaneously then those */ /* stations are additionally included regardless */ /* of the latitude limits. */ /* [-lo LonLimits] Limits on station longitudes. 'LonLimits' is */ /* of the form MinLat-MaxLat (e.g. 15.3-30.4). */ /* Only stations within these limits are */ /* included. If -o is specified simultaneously */ /* then those stations are additionally included */ /* regardless of the longitude limits. */ /* IAGAFile Name of IAGA-format file. */ /* NewIAGAFile Name of generated IAGA-format file. */ /* */ /****************************************************************************/ /****************************************************************************/ /* Lasse Hakkinen */ /* Finnish Meteorological Institute */ /* Geophysical Research Division */ /* P.O.Box 503 */ /* FIN-00101, Helsinki, Finland */ /* e-mail: Lasse.Hakkinen@fmi.fi */ /* phone : (+358)-9-19294634 */ /* fax : (+358)-9-19294603 */ /* */ /* version 1.05 09.01.2020 */ /****************************************************************************/ /****************************************************************************/ /* Version history: */ /* */ /* 1.05 09.01.2020 Date strings must be YYYYMMDD (four digits for year) */ /* Replaced StrToSecs -> StrToSecsC and */ /* SecsToStr -> SecsToStrC. */ /* 1.04 07.04.2011 Added -la and -lo options for latitude and longitude */ /* limits respectively. */ /* 1.03 09.09.1999 Fixed a Y2K bug in NewTime.h file which resulted in */ /* incorrect year in date strings if year >= 2000. */ /* 1.02 18.3.1999 Changed -h option so that the argument may be a decimal */ /* number so that fractional hours are permitted. */ /* 1.01 26.2.1996 Cosmetic changes in code. No apparent change in program */ /* behaviour. */ /* 1.0 10.10.1995 First official release */ /****************************************************************************/ #include #include #include #include "Usage.h" #include "MagnData.h" #include "IAGA.h" #define BuffSize 1440 /* Size of one block in an IAGA file */ char *version = "1.05"; char *date = "09.01.2020"; #define HeaderLineCount 4 #define UsageLineCount 27 char *HeaderText[HeaderLineCount] = { "**************************************************************************", "This program extracts data for given time interval or for given stations ", "from an IAGA format magnetometer data file. ", "**************************************************************************", }; char *UsageText[UsageLineCount] = { " [-s] [-e | -h] [-o] [<] IAGAFile > NewIAGAFile", " [-s YYYYMMDDHH] Time of the first record included. If missing ", " then start of file is assumed. ", " [-e YYYYMMDDHH] Time of the record not included anymore. ", " If missing then end of file is assumed. ", " [-h HH] Number of hours included. Either -e or -h can ", " be specified, not both. HH may be a decimal ", " number so that fractional hours are permitted.", " [-o 'Station list'] List of stations enclosed in quotes ", " If missing then all stations included. ", " Stations are identified by three-letter code ", " and separated by exactly one space. ", " e.g. 'SOR KEV KIL'. ", " [-la LatLimits] Limits on station latitudes. 'LatLimits' is of", " the form MinLat-MaxLat (e.g. 45.3-62.4). Only ", " stations within these limits are included. ", " If -o is specified simultaneously then those ", " stations are additionally included regardless ", " of the latitude limits. ", " [-lo LonLimits] Limits on station longitudes. 'LonLimits' is ", " of the form MinLat-MaxLat (e.g. 15.3-30.4). ", " Only stations within these limits are ", " included. If -o is specified simultaneously ", " then those stations are additionally included ", " regardless of the longitude limits. ", " IAGAFile Name of IAGA-format file. ", " NewIAGAFile Name of extracted IAGA-format file. ", }; /*--------------------------------------------------------------------------*/ /* Extract the two floats from the string of form 45.3-86.2 */ /*--------------------------------------------------------------------------*/ long GetLimits(char *Str, long *Min, long *Max) { float fMin,fMax; long count; count = sscanf(Str,"%f-%f",&fMin,&fMax); if (fMin > fMax) fMin -= 360.0; *Min = RoundFloat(100.0*fMin); *Max = RoundFloat(100.0*fMax); return(count); } long CheckLimits(char *Str, long Min, long Max) { long Value; char Value_str[10] = "xxxxx"; strncpy(Value_str, Str,5); Value = atol(Value_str); if (Value > 18000) Value -= 36000; // Set Value from -180 to +180 if ((Min <= Value) && (Value <= Max)) return 1; else return 0; } /*--------------------------------------------------------------------------*/ /* The main procedure */ /*--------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { long params; long status = 0; long FileCount = 0; char FileName[100]; /* Name of the original data file */ Time_sec Time; /* Time of the current data block (seconds) */ Time_sec StartTime = MIN_TIME; /* Time of first data block (seconds) */ Time_sec EndTime = MAX_TIME; /* No blocks included after this time */ double HourCount = 0.0; /* Number of hours included */ char Buffer[BuffSize]; /* Buffer for one data block */ char StationList[200] = ""; /* List of stations from command line */ FILE *IAGAFile; /* IAGA format data file to be processed */ char LatStr[100] = ""; /* Latitude limits, e.g. 45.6-64.2 */ char LonStr[100] = ""; /* Longitude limits, e.g. -10.6--5.2 */ long Lat_min, Lat_max; /* Limits of latitude in 1/100 degrees */ long Lon_min, Lon_max; /* Limits of longitude in 1/100 degrees */ long LatFlag, LonFlag; char ID[10] = "xxx"; /*==========================*/ /* Analyse the command line */ /*==========================*/ if (argc == 1) { /* No arguments, show the usage text */ PrintUsage(argv[0],0,HeaderLineCount,UsageLineCount); return OK; } for (params = 1; params < argc; params++) { if (*argv[params] != '-') { strcpy(FileName,argv[params]); FileCount++; } else { switch (*(argv[params]+1)) { case 's' : StartTime = StrToSecsC(argv[++params],0); break; case 'e' : EndTime = StrToSecsC(argv[++params],0); break; case 'h' : HourCount = atof(argv[++params]); break; case 'o' : strcpy(StationList,argv[++params]); break; case 'l' : switch (*(argv[params]+2)) { case 'a' : strcpy(LatStr,argv[++params]); break; case 'o' : strcpy(LonStr,argv[++params]); break; } break; default : fprintf(stderr,"\n### %s: \"%s\" is not an option.\n\n", argv[0], argv[params]); PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount); return FAIL; break; } } } /*====================================*/ /* Check the values of the parameters */ /*====================================*/ if (FileCount > 1) { PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount); return FAIL; } if ((HourCount != 0.0) && (EndTime != MAX_TIME)) { PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount); return FAIL; } if ((HourCount != 0.0) && (StartTime == MIN_TIME)) { PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount); return FAIL; } if (HourCount != 0.0) { EndTime = StartTime + (long)(3600*HourCount+0.5); } if (strlen(LatStr) > 0) { if (GetLimits(LatStr,&Lat_min, &Lat_max) != 2) { fprintf(stderr,"\n### Wrong format in -la option: %s\n",LatStr); return FAIL; } } if (strlen(LonStr) > 0) { if (GetLimits(LonStr,&Lon_min, &Lon_max) != 2) { fprintf(stderr,"\n### Wrong format in -la option: %s\n",LonStr); return FAIL; } } /*===========================*/ /* Try to open the IAGA file */ /*===========================*/ if (FileCount == 0) IAGAFile = stdin; else { if ((IAGAFile = fopen(FileName, "r")) == NULL) { fprintf(stderr,"\n### %s - Unable to open file: %s\n",argv[0],FileName); return FAIL; } } /*===================================*/ /* Extract proper data from the file */ /*===================================*/ while (ReadIAGABlock(IAGAFile,Buffer) && ((Time = GetIAGATime(Buffer)) < EndTime)) { if (Time >= StartTime) { if ((strlen(LatStr) > 0) || (strlen(LonStr) > 0)) { if ((strlen(StationList) > 0) && StationInList(Buffer+IAGA_StationID,StationList)) WriteIAGABlock(stdout,Buffer); else { if ((strlen(LatStr) > 0) && (CheckLimits(Buffer+IAGA_Latitude, Lat_min, Lat_max) == 0)) LatFlag = 0; else LatFlag = 1; if ((strlen(LonStr) > 0) && (CheckLimits(Buffer+IAGA_Longitude, Lon_min, Lon_max) == 0)) LonFlag = 0; else LonFlag = 1; if (LatFlag && LonFlag) WriteIAGABlock(stdout,Buffer); } } else { if (StationInList(Buffer+IAGA_StationID,StationList)) WriteIAGABlock(stdout,Buffer); } } } if (FileCount == 1) fclose(IAGAFile); return OK; }