/* * Usage: ./newrex_c data/20070105_003031/rex_003031500?_*.fit * * Extract and output table of data from New Horizons REX data sets, * using PDS label to locate data within FITS files. * */ #include #include #include /* Swap bytes in-place for n-byte value */ void doswap(void* pv, int n) { char c1; static int16_t i2= 256; char* p = (char*) &i2; if (*p) return; for ( --n, p=pv; n>0; p++, n-=2 ) { c1 = *p; *p = p[n]; p[n] = c1; } return; } /* Structure to aid in parsing PDS label statement ^POINTER = ( "FILE.FIT", 1) */ typedef struct KVstr { int count; char line[100]; char kwd[80]; char tokens[2][80]; long nCount; long n; } KV; /* Parse PDS label statement ^POINTER = ( "FILE.FIT", 1) */ KV *readKVPointer(FILE* f) { static KV kv; /* KV structure for return pointer */ char tmp[100]; char* pLine; int n; kv.nCount = kv.count = -1; /* kv.count = -1 => failure e.g. EOF */ kv.tokens[0][0] = kv.tokens[1][0] = '\0'; if ( !fgets( kv.line, 100, f) ) return &kv; /* Read one line from PDS label file stream; return on failure (e.g. EOF) */ kv.count = 0; /* No EOF, set kv.count to zero */ if ( (pLine=strchr(kv.line,'\n')) ) *pLine = '\0'; /* Null-terminate at newline, if present */ if ( (pLine=strchr(kv.line,'\r')) ) *pLine = '\0'; /* Null-terminate at carriage return, if present */ for ( pLine=kv.line; *pLine && *pLine==' '; ++pLine ); /* Set pointer to first non-space character */ /* Read keyword, equals sign + open paren + whitespace, filename, * comma and whitespace, integer pointer to data record */ /* %kwd %=(" %X.F" %, %N */ n = sscanf( pLine, "%[^ =]%[ =(\"]%[^ ,]%[ ,]%[^)]%[)]", kv.kwd, tmp, kv.tokens[0], tmp, kv.tokens[1], tmp ); if (n!=6) { /* Set kv.count to sscanf return value if six items were not read */ if (n>-1) kv.count = n; /* and if sscanf did not return -1 (failure?) */ return &kv; } kv.count = 2; /* Six parameters strings were read, set count to 2 for pointer filename and record number */ kv.nCount = sscanf( kv.tokens[1], "%ld", &kv.n); /* Try to read record number string */ return &kv; } /* Read PDS labels, output table of * values from corresponding FITS file */ int main(int ac, char** av) { int iAc; float iqCal[1250][2]; /* IQ, Calibrated */ float rtCal[10][2]; /* Radiometry and Time Tags (RT), Calibrated */ int16_t iqRaw[1250][2]; /* IQ, Raw */ struct RTRAW { int64_t rad; int32_t ttg; } rtRaw[10]; /* Radiometry and Time Tags (RT), Raw */ KV *pKV; /* Pointer to structure for parsing PDS label pointers */ FILE* f; /* File stream pointer */ for (iAc=1; iAccount<0 ) { /* Exit if EOF */ perror("EOF; exiting"); return 1; }; if ( pKV->count<1 ) continue; /* Ignore blank lines */ if ( pKV->count==2 && pKV->nCount==1 ) { /* Check for pointer */ if ( ! strcmp( pKV->kwd, "^EXTENSION_IQVALS_TABLE") ) { /* IQ FITS BINTABLE pointer */ iqRec0 = pKV->n; /* Save record pointer */ isRaw = strstr(pKV->tokens[0],"_ENG_") ? 1 : 0; /* _ENG_ in filename pointer means this is raw data */ continue; /* Continue to next iteration through loop */ } if ( ! strcmp( pKV->kwd, "^EXTENSION_RAD_TIME_TAGS_TABLE") ) { /* RT FITS BINTABLE pointer */ rtRec0 = pKV->n; /* Save record pointer */ continue; /* Continue to next iteration */ } } if ( ! strcmp( pKV->kwd, "END" ) ) { /* Error if END found */ perror("PDS END statement; exiting"); return 1; } } /* End of PDS label parsing while loop */ fclose(f); /* Close PDS label */ strcpy(av[iAc]+strlen(av[iAc])-3,"fit"); /* Build FITS filepath - replace lbl with fit */ f = fopen(av[iAc],"r"); /* Open FITS file stream */ fseek( f, 2880L * (iqRec0 - 1), SEEK_SET); /* Seek to IQ BINTABLE */ if ( isRaw) { fread( iqRaw[0], 1, sizeof iqRaw, f); /* - Read Raw data */ for (i=0;i<1250;++i) for (j=0;j<2;++j) doswap(iqRaw[i]+j,2); /* - Byte-swap Raw data */ } else { fread( iqCal[0], 1, sizeof iqCal, f); /* - Read Calibrated data */ for (i=0;i<1250;++i) for (j=0;j<2;++j) doswap(iqCal[i]+j,4); /* - Byte-swap Raw data */ } // RT fseek( f, 2880L * (rtRec0 - 1), SEEK_SET); /* Seek to IQ BINTABLE */ if ( isRaw) { for (i=0; i<10; ++i) { fread( rtRaw+i, 1, 12, f); /* - Read Calibrated data one row at a time */ doswap(&rtRaw[i].rad,8); /* - Byte-swap Calibrated Radiometry */ doswap(&rtRaw[i].ttg,4); /* - Byte-swap Calibrated Time Tags */ } } else { fread( rtCal[0], 1, sizeof rtCal, f); /* - Read Calibrated data */ for (i=0;i<10;++i) for (j=0;j<2;++j) doswap(rtCal[i]+j,4); /* - Byte-swap Raw data */ } fclose(f); /* Close FITS file stream */ /* Output * - 10 rows of row number + IQ + RT data * - 1250 rows of row number + IQ data */ if ( isRaw) { for (i=0; i<10; ++i) fprintf(stdout, "%5d%16d%16d%16ld%16d\n", i+1, iqRaw[i][0], iqRaw[i][1], rtRaw[i].rad, rtRaw[i].ttg); for (i=10; i<1250; ++i) fprintf(stdout, "%5d%16d%16d\n", i+1, iqRaw[i][0], iqRaw[i][1]); } else { for (i=0; i<10; ++i) fprintf(stdout, "%5d%16.4f%16.4f%16.4f%16.4f\n", i+1, iqCal[i][0], iqCal[i][1], rtCal[i][0], rtCal[i][1]); for (i=10; i<1250; ++i) fprintf(stdout, "%5d%16.4f%16.4f\n", i+1, iqCal[i][0], iqCal[i][1]); } } return 0; }