/********************************************************************* * Program Name : GOESOUT - GOES Output Table Generator * Version : See below * Author : Dan Wilkinson * Date Written : September 2, 1997 * Date Updated : September 2, 1997 * Function : Create an ASCII table of a GOES 5-min data file. * The user specifies the incoming and outgoing filenames * and the starting and ending days of the month. * These values are passed are command line arguments. * * i.e., goesout input output day1 day2 ion * goesout i0759706.bin i0759706.asc 23 24 p * * This program must link with dcwSwap.c & dcwSwap.h * Most of the code in this program is from the GOES plot program. * ******************************************************************/ #include #include #include /* #include */ #include #include "dcwswap.h" #define VERSION 0.1 #define ZERODATA 32700 #define BADDATA 32711 #define PLOTP 1 #define PLOTXM 2 #define PLOTALL 3 #define INPERROR -1 #define OUTERROR -2 #define BADHEADER -3 #define FALSE 0 #define TRUE 1 #define GOOD 1 #define BAD 0 /***** The binary integers used in the GOES 5-min data format are two's complement with the bytes in increasing order of significance (Little Endian). The following table lists how this compares to some popular computer prcessors. If your computer does not default to the PC representation, you will have to swap bytes accordingly. This list was prepared from word-of-mouth only! If you have additions or corrections please call me: Dan Wilkinson (303) 497-6137 dcw@mail.ngdc.noaa.gov INTEGER BYTE ORDER 16-BIT 32-BIT -------------------------------- FITS B1 B0 B3 B2 B1 B0 Must Swap MOTOROLA B1 B0 B3 B2 B1 B0 Must Swap DATA GENERAL B1 B0 B3 B2 B1 B0 Must Swap MACINTOSH B1 B0 B3 B2 B1 B0 Must Swap APOLLO B1 B0 B3 B2 B1 B0 Must Swap SPARC B1 B0 B3 B2 B1 B0 Must Swap SUN B1 B0 B3 B2 B1 B0 Must Swap IBM 360/370 B1 B0 B3 B2 B1 B0 Must Swap INTEL B0 B1 B0 B1 B2 B3 IBM PC B0 B1 B0 B1 B2 B3 VAX B0 B1 B0 B1 B2 B3 DEC STATION B0 B1 B0 B1 B2 B3 PDP B0 B1 B2 B3 B0 B1 -------------------------------- This program will swap bytes when SWAPBYTES is definedin dcwSwap.h Comment out "#define SWAPBYTES" when swapping is not necessary. */ /***** Define DEBUG and DEBUG_OPEN to print useful process information to DebugStream *****/ #define DEBUG #define DEBUG_OPEN #define SWORD1 0 #define SWORD2 1 #define JDAY 2 #define DMIN 3 #define XL 4 #define XS 5 #define HP 6 #define HE 7 #define HN 8 #define HT 9 #define E1 10 #define P1 11 #define P2 12 #define P3 13 #define P4 14 #define P5 15 #define P6 16 #define P7 17 FILE *InputStream, *OutputStream, *DebugStream; char InFile[40], OutFile[40], DebugFile[40]; char DebugFile[40] = "/tmp/goesout.dbg"; short DayStart, DayEnd; short dcwOpenFiles( short argc, char **argv, FILE **InputStream, FILE **OutputStream, short *DayStart, short *DayEnd ); void dcwIntro( void ); float x_float(short x_flux); float h_float(short h_flux); float p_float(short p_flux); short read_header( FILE *InputStream ); short leap_year(void); short dcwWriteHeader( FILE *OutputStream ); short read_line( FILE *InputStream ); short write_line( FILE *OutputStream ); short find_time(void); short dcwSwapInputBuffer( void ); /* Set to display all (PLOTALL) data types */ short PlotFrames = 3; short DAYSUM[13]={0, /* Number of days since beginning of the year */ 0,31,59,90,120,151,181,212,243,273,304,334 }; char *Months[13]={"", "January","February","March","April","May","June", "July","August","September","October","November","December" }; struct { short satid; short year; short month; short day; short minod; short hour; short min; short doy; short type; short res; } Header; short InputBuffer[18]; /*************************************************************** * Function Name: main * Author : Dan Wilkinson * Date : September 2, 1997 * Function : Recognize arguments and execute corresponding * : subroutines ***************************************************************/ short main( short argc, char *argv[] ) { short CurrentDay, Success; /***** Read the command line arguments and open the specified files. *****/ if ( dcwOpenFiles( argc, argv, &InputStream, &OutputStream, &DayStart, &DayEnd ) == BAD ){ dcwIntro(); return(0); } /***** Read the header and parse the results into structure info *****/ if ( ( Success = read_header( InputStream )) != 1 ){ if (Success==BADHEADER) { printf("Wrong input file format.\n"); } else { printf("Error reading from input file.\n"); } fclose( InputStream ); fclose( OutputStream ); return 1; } leap_year(); CurrentDay=1; printf("Working."); /***** Write the header to the ASCII file. *****/ if(dcwWriteHeader( OutputStream )==OUTERROR){ printf("\nError writing to output file.\n"); fclose( InputStream ); fclose( OutputStream ); return 1; } /***** Read binary input records and write ASCII ones. *****/ while(!feof( InputStream ) && DayEnd >= CurrentDay ){ if ( read_line( InputStream ) != GOOD ){ printf("\nError reading from input file.\n"); fclose( InputStream ); fclose( OutputStream ); return 1; } if ( Header.day >= DayStart ){ if ( write_line( OutputStream ) != GOOD ){ printf("\nError writing to output file.\n"); fclose( InputStream ); fclose( OutputStream ); return 1; } if( Header.day != CurrentDay){ CurrentDay=Header.day; printf("."); } } } printf("Done\n"); fclose( InputStream ); fclose( OutputStream ); #ifdef DEBUG_OPEN fclose( DebugStream ); #endif return 0; } /******************************************************************** * Function Name: dcwSwapInputBuffer * Author : Dan Wilkinson * Date : September 11, 1997 * Function : Swap all words in the input InputBuffer. *********************************************************************/ short dcwSwapInputBuffer( void ) { short Index=0; for( Index = 0; Index <= 17; ++Index){ dcwSwapBytes( (char *) &(InputBuffer[Index]), TWO_BYTES ); } return( GOOD ); } /*************************************************************** * Function name: read_header * Author : Greg Ushomirskiy * Date : April 1992 * Function : Read and interpret input header ***************************************************************/ short read_header( FILE *InputStream ) { if( fread( InputBuffer, 2, 18, InputStream )!=18) return INPERROR; #ifdef DEBUG_OPEN fprintf( DebugStream, "Before Swapping Bytes satid = %hd\n ", InputBuffer[0] ); #endif dcwSwapInputBuffer(); #ifdef DEBUG_OPEN fprintf( DebugStream, "After Swapping Bytes satid = %hd\n ", InputBuffer[0] ); #endif Header.satid=InputBuffer[0]; Header.year=InputBuffer[1]; Header.type=InputBuffer[2]; if (( Header.type < 102 )||(Header.type>106)){ #ifdef DEBUG fprintf( DebugStream, "Header.type in error:%hd\n", Header.type ); #endif return BADHEADER; } Header.res=InputBuffer[3]; if (( Header.res!=1 )&&( Header.res!=5 )){ #ifdef DEBUG fprintf( DebugStream, "Header.res in error:\n", Header.res ); #endif return BADHEADER; } Header.month=InputBuffer[4]; if (( Header.month<1)||( Header.month>12 )) return BADHEADER; return 1; } /*************************************************************** * Function name: read_line * Author : Dan Wilkinson * Date : September 4, 1997 * Function : Read a data record. ***************************************************************/ short read_line( FILE *InputStream ) { if( fread( InputBuffer, 2, 18, InputStream ) != 18 ) /* Read a record from input file */ { if( !feof( InputStream ) ) return INPERROR; else return 1; } dcwSwapInputBuffer(); Header.doy=InputBuffer[JDAY]; Header.minod=InputBuffer[DMIN]; #ifdef DEBUG fprintf( DebugStream, "Header.doy = InputBuffer[JDAY]: %hd = %hd\n", Header.doy, InputBuffer[JDAY] ); fprintf( DebugStream, "Header.minod = InputBuffer[DMIN]: %hd = %hd\n", Header.minod, InputBuffer[DMIN] ); #endif find_time(); #ifdef DEBUG fprintf( DebugStream, "Header.day= %hd\n", Header.day ); fprintf( DebugStream, "Header.hour= %hd\n", Header.hour ); fprintf( DebugStream, "Header.min= %hd\n", Header.min ); #endif return GOOD; } /*************************************************************** * Function name: leap_year * Author : Greg Ushomirskiy * Date : April 1992 * Function : Adjust DAYSUM[] array if processing leap year ***************************************************************/ short leap_year(void) { short month; short leap=0; if (Header.year%4==0) leap=1; for (month=3;month<=12;month++) DAYSUM[month]+=leap; return 1; } /*************************************************************** * Function name: write_line * Author : Greg Ushomirskiy * Date : April 1992 * Function : Convert a line of input and write to output ***************************************************************/ short write_line( FILE *OutputStream ) { short s; switch(PlotFrames) /* Now print to output */ { case PLOTALL: s=fprintf( OutputStream, "%2.2d%2.2d%2.2d %2.2d%2.2d " "%3.3d" " % 8.2E % 8.2E" "% 9.2f% 9.2f" "% 9.2f% 9.2f" " % 8.2E" " % 8.2E % 8.2E" " % 8.2E % 8.2E" " % 8.2E % 8.2E" " % 8.2E\n", Header.year, Header.month, Header.day, Header.hour, Header.min, Header.doy, x_float (InputBuffer[4]), x_float (InputBuffer[5]), h_float (InputBuffer[6]), h_float (InputBuffer[7]), h_float (InputBuffer[8]), h_float (InputBuffer[9]), p_float (InputBuffer[10]), p_float (InputBuffer[11]), p_float (InputBuffer[12]), p_float (InputBuffer[13]), p_float (InputBuffer[14]), p_float (InputBuffer[15]), p_float (InputBuffer[16]), p_float (InputBuffer[17]) ); break; case PLOTXM: s=fprintf(OutputStream, "%2.2d%2.2d%2.2d %2.2d%2.2d " "%3.3d" " % 8.2E % 8.2E" "% 9.2f% 9.2f" "% 9.2f% 9.2f\n", Header.year, Header.month, Header.day, Header.hour, Header.min, Header.doy, x_float (InputBuffer[4]), x_float (InputBuffer[5]), h_float (InputBuffer[6]), h_float (InputBuffer[7]), h_float (InputBuffer[8]), h_float (InputBuffer[9]) ); break; case PLOTP: s=fprintf(OutputStream, "%2.2d%2.2d%2.2d %2.2d%2.2d " "%3.3d" " % 8.2E" " % 8.2E % 8.2E" " % 8.2E % 8.2E" " % 8.2E % 8.2E" " % 8.2E\n", Header.year, Header.month, Header.day, Header.hour, Header.min, Header.doy, p_float (InputBuffer[10]), p_float (InputBuffer[11]), p_float (InputBuffer[12]), p_float (InputBuffer[13]), p_float (InputBuffer[14]), p_float (InputBuffer[15]), p_float (InputBuffer[16]), p_float (InputBuffer[17]) ); break; } if (s==EOF) return OUTERROR; return 1; } /*************************************************************** * Function name: find_time * * Author : Greg Ushomirskiy * * Date : April 1992 * * Function : Convert day-of-year and minute-of-day to * * : regular time. * ***************************************************************/ short find_time(void) { Header.day=Header.doy-DAYSUM[Header.month]; Header.hour=Header.minod/60; Header.min=Header.minod%60; return 1; } /******************************************************************** * Function Name: x_float * * Author : Dan Wilkinson * * Date : December 7, 1990 * Function : Uncompress a x-ray word. * *********************************************************************/ float x_float ( short x_flux ) { if ( x_flux == BADDATA ) return ( (float) BADDATA ); if ( x_flux == ZERODATA ) return ( 0.F ); return ( (float) pow ( (double) 10, (double) x_flux / 1000 ) ); } /******************************************************************** * Function Name: h_float * * Author : Dan Wilkinson * * Date : December 7, 1990 * Function : Uncompress a magnetometer word. * *********************************************************************/ float h_float ( short h_flux ) { /* if ( h_flux == BADDATA ) return ( (float) BADDATA ); */ if ( h_flux == ZERODATA ) return ( 0.F ); return ( (float) ( (float) h_flux / 100.F ) ); } /******************************************************************** * Function Name: p_float * * Author : Dan Wilkinson * * Date : December 7, 1990 * Function : Uncompress a particle word. * *********************************************************************/ float p_float ( short p_flux ) { if ( p_flux == BADDATA ) return ( (float) BADDATA ); if ( p_flux == ZERODATA ) return ( 0.F ); return ( (float) pow ( (double) 10, (double) p_flux / 1000 ) ); } /******************************************************************** * Function Name: dcwWriteHeader * * Author : Dan Wilkinson * * Date : March 8, 1991 * Function : Print header info to ASCII data file. * *********************************************************************/ short dcwWriteHeader( FILE *OutputStream ) { short s; s=fprintf( OutputStream, "GOES-%1d SPACE ENVIRONMENT MONITOR (%1d-Min Avgs)\n\n", Header.satid, Header.res ); if (s==EOF) return OUTERROR; s=fprintf( OutputStream, "Start: %s %2hd, 19%2.2hd 0005 UT\n", Months[ Header.month ], DayStart, Header.year ); s=fprintf( OutputStream, "End : %s %2hd, 19%2.2hd 2355 UT\n\n", Months[ Header.month ], DayEnd, Header.year ); if (s==EOF) return OUTERROR; switch(PlotFrames){ case PLOTALL: s=fprintf(OutputStream, "XL 1-8 Ang X-ray Flux (Watts/Meter2)\n" "XS .5-4 Ang X-ray Flux (Watts/Meter2)\n" "Hp (parallel) Northward Magnetic Flux (nanotesla)\n" "He Earthward Magnetic Flux (nanotesla)\n" "Hn (normal) Eastward Magnetic Flux (nanotesla)\n" "Ht Total Magnetic Flux (nanotesla)\n" ); if (s==EOF) return OUTERROR; case PLOTP: switch(Header.type){ case 102: /* uncorrected protons */ s=fprintf(OutputStream, "E1 >= 2 MeV electrons (Counts/cm2 sec sr) Uncorrected\n" "P1 .6 - 4.2 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P2 4.2 - 8.7 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P3 8.7 - 14.5 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P4 15.0 - 44.0 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P5 39.0 - 82.0 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P6 84.0 - 200.0 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P7 110.0 - 500.0 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" ); if (s==EOF) return OUTERROR; break; case 103: /* corrected protons */ s=fprintf(OutputStream, "E1 >= 2 MeV electrons (Counts/cm2 sec sr) Uncorrected\n" "P1 .6 - 4.2 MeV protons (Counts/cm2 sec sr MeV) Corrected\n" "P2 4.2 - 8.7 MeV protons (Counts/cm2 sec sr MeV) Corrected\n" "P3 8.7 - 14.5 MeV protons (Counts/cm2 sec sr MeV) Corrected\n" "P4 15.0 - 44.0 MeV protons (Counts/cm2 sec sr MeV) Corrected\n" "P5 39.0 - 82.0 MeV protons (Counts/cm2 sec sr MeV) Corrected\n" "P6 84.0 - 200.0 MeV protons (Counts/cm2 sec sr MeV) Corrected\n" "P7 110.0 - 500.0 MeV protons (Counts/cm2 sec sr MeV) Corrected\n" ); if (s==EOF) return OUTERROR; break; case 104: /* integrated protons */ s=fprintf(OutputStream, "E1 >= 2 MeV electrons (Counts/cm2 sec sr) Uncorrected\n" "I1 > 1 MeV protons (Counts/cm2 sec sr) Corrected\n" "I2 > 5 MeV protons (Counts/cm2 sec sr) Corrected\n" "I3 > 10 MeV protons (Counts/cm2 sec sr) Corrected\n" "I4 > 30 MeV protons (Counts/cm2 sec sr) Corrected\n" "I5 > 50 MeV protons (Counts/cm2 sec sr) Corrected\n" "I6 > 60 MeV protons (Counts/cm2 sec sr) Corrected\n" "I7 > 100 MeV protons (Counts/cm2 sec sr) Corrected\n" ); if (s==EOF) return OUTERROR; break; case 105: /* uncorrected alphas */ s=fprintf(OutputStream, "E1 >= 2 MeV electrons (Counts/cm2 sec sr) Uncorrected\n" "A1 3.8 - 9.9 MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" "A2 9.9 - 21.3 MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" "A3 21.3 - 61. MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" "A4 60.0 - 180 MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" "A5 160.0 - 260 MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" "A6 330.0 - 500 MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" ); if (s==EOF) return OUTERROR; break; case 106: /* HEPAD */ s=fprintf(OutputStream, "E1 >= 2 MeV electrons (Counts/cm2 sec sr) Uncorrected\n" "P8 370 - 480 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P9 480 - 640 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P10 640 - 850 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "P11 > 850 MeV protons (Counts/cm2 sec sr MeV) Uncorrected\n" "A7 630 - 850 MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" "A8 > 850 MeV alpha-particles (Counts/cm2 sec sr MeV) Uncorrected\n" ); if (s==EOF) return OUTERROR; break; } s=fprintf(OutputStream, "\n" ); if (s==EOF) return OUTERROR; break; case PLOTXM: s=fprintf(OutputStream, "XL 1-8 Ang X-ray Flux (Watts/Meter2)\n" "XS .5-4 Ang X-ray Flux (Watts/Meter2)\n" "Hp (parallel) Northward Magnetic Flux (nanotesla)\n" "He Earthward Magnetic Flux (nanotesla)\n" "Hn (normal) Eastward Magnetic Flux (nanotesla)\n" "Ht Total Magnetic Flux (nanotesla)\n\n" ); if (s==EOF) return OUTERROR; break; } s = fprintf(OutputStream, "Bad Mag data are filled with: 327.11\n" "Bad X-ray and Particle data are filled with 3.27E+04\n\n"); /* s=fprintf(OutputStream, "Bad data filled with: 32711 ( 3.27E+04 in Eponential Display Format )\n\n"); */ if (s==EOF) return OUTERROR; switch(PlotFrames){ case PLOTALL: switch(Header.type){ case 102: /* uncorrected protons */ case 103: /* corrected protons */ s=fprintf(OutputStream, "YYMMDD HHMM DAY XL XS HP HE HN HT E1 P1 P2 P3 P4 P5 P6 P7\n" "--------------------------------------------------------------------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; case 104: /* integrated protons */ s=fprintf(OutputStream, "YYMMDD HHMM DAY XL XS HP HE HN HT E1 I1 I2 I3 I4 I5 I6 I7\n" "-------------------------------------------------------------------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; case 105: /* uncorrected alphas */ s=fprintf(OutputStream, "YYMMDD HHMM DAY XL XS HP HE HN HT E1 A1 A2 A3 A4 A5 A6 \n" "-------------------------------------------------------------------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; case 106: /* HEPAD */ s=fprintf(OutputStream, "YYMMDD HHMM DAY XL XS HP HE HN HT E1 P8 P9 P10 P11 A7 A8 \n" "-------------------------------------------------------------------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; } break; case PLOTXM: s=fprintf(OutputStream, "YYMMDD HHMM DAY XL XS HP HE HN HT\n" "-----------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; case PLOTP: switch(Header.type){ case 102: /* uncorrected protons */ case 103: /* corrected protons */ s=fprintf(OutputStream, "YYMMDD HHMM DAY E1 P1 P2 P3 P4 P5 P6 P7\n" "-----------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; case 104: /* integrated protons */ s=fprintf(OutputStream, "YYMMDD HHMM DAY E1 I1 I2 I3 I4 I5 I6 I7\n" "-----------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; case 105: /* uncorrected alphas */ s=fprintf(OutputStream, "YYMMDD HHMM DAY E1 A1 A2 A3 A4 A5 A6 \n" "-----------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; case 106: /* HEPAD */ s=fprintf(OutputStream, "YYMMDD HHMM DAY E1 P8 P9 P10 P11 A7 A8 \n" "-----------------------------------------------------------------------------------------------\n"); if (s==EOF) return OUTERROR; break; } break; } return 1; } /******************************************************************** * Function Name: dcwOpenFiles * Author : Dan Wilkinson * Date : August 19, 1992 * Function : Open input and output files. * The user can pass the file names via command line * parameters. Otherwise the program will prompt for * the names. i.e., goesout input output day1 day2 ion *********************************************************************/ short dcwOpenFiles( short argc, char **argv, FILE **InputStream, FILE **OutputStream, short *DayStart, short *DayEnd ) { if( argc == 5 ){ /***** parameter 2 will be input file name *****/ sprintf( InFile, "%s", *(argv+1) ); /***** parameter 2 will be input file name *****/ sprintf( OutFile, "%s", *(argv+2) ); /***** Decode days to start and end output *****/ sscanf( argv[3], "%hd", DayStart ); sscanf( argv[4], "%hd", DayEnd ); /***** parameter 2 will be input file name *****/ /* *IonType = tolower( *argv[5] ); */ printf("\nInput file Name : %s\n" "Output file Name : %s\n" "Day to Start : %hd\n" "Day to End : %hd\n", InFile, OutFile, *DayStart, *DayEnd ); /***** Verify the arguments - open files *****/ *InputStream = fopen( InFile,"rb"); if( *InputStream == NULL ) { printf("\n***** Error Opening Input.\n"); return( BAD ); } *OutputStream = fopen( OutFile,"wt"); if( *OutputStream == NULL ) { printf("\n***** Error Opening Output.\n"); return( BAD ); } if( *DayStart < 1 || *DayStart > *DayEnd || *DayStart > 31 || *DayEnd < 1 || *DayEnd > 31 ) { printf("\n***** Improper Days Entered.\n"); return( BAD ); } } else{ /* Not enough arguments. */ printf("\n***** Wrong number of arguments.\n"); return( BAD ); } #ifdef DEBUG_OPEN DebugStream = fopen( DebugFile, "wt" ); #endif return( GOOD ); } /******************************************************************** * Function Name: dcwIntro * Author : Dan Wilkinson * Date : September 3, 1997 * Function : Print a program introduction to screen. *********************************************************************/ void dcwIntro( void ) { printf( "\n G O E S O U T version(%4.1f)\n\n", VERSION ); printf( " This program will print out an ASCII table of GOES\n" " 5-min averages. The user must specify the \n" " input filename, output filename, start day, and end day.\n\n" " Example: goesout i0759701.bin i0759701.asc 1 2\n\n" ); }