374 lines
12 KiB
C
374 lines
12 KiB
C
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@file fitsort.c
|
|
@author Nicolas Devillard
|
|
@date May 1st, 1996
|
|
@version $Revision: 1.4 $
|
|
@brief Sorts out FITS keywords
|
|
|
|
The input is a succession of FITS headers delivered through stdin by
|
|
'dfits'. On the command line, specify which keywords you wish to display, the
|
|
output contains for each file, the file name and the keyword values in
|
|
column format. Example:
|
|
|
|
dfits *.fits | fitsort BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
|
|
The output would be like:
|
|
File BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
|
|
image1.fits 32 2 256 256
|
|
image2.fits -32 3 128 128 40
|
|
|
|
Using 'fitsort -d ...' would prevent printing the first line (filename and
|
|
keyword names).
|
|
The output format is simple: values are separated by tabs, records by
|
|
linefeeds. When no value is present (no keyword in this header), only a tab
|
|
is printed out. Example:
|
|
|
|
file1.fits contains NAXIS1=100 NAXIS2=200
|
|
file2.fits contains NAXIS1=20
|
|
dfits file1.fits file2.fits | fitsort NAXIS2 NAXIS1
|
|
would litterally print out (\t stands for tab, \n for linefeed):
|
|
file1.fits\t200\t100\n
|
|
file2.fits\t\t20\n
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/*
|
|
$Id: fitsort.c,v 1.4 2005/07/04 14:21:31 yjung Exp $
|
|
$Author: yjung $
|
|
$Date: 2005/07/04 14:21:31 $
|
|
$Revision: 1.4 $
|
|
*/
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Include
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Define
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
#define MAX_STRING 128
|
|
#define MAX_KEY 512
|
|
#define FMT_STRING "%%-%ds\t"
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
New types
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/* This holds a keyword value and a flag to indicate its presence */
|
|
typedef struct _KEYWORD_ {
|
|
char value[MAX_STRING] ;
|
|
int present ;
|
|
} keyword ;
|
|
|
|
/* Each detected file in input has such an associated structure */
|
|
typedef struct _RECORD_ {
|
|
char filename[MAX_STRING] ;
|
|
keyword listkw[MAX_KEY] ;
|
|
} record ;
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Function prototypes
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
static int isfilename(char *string) ;
|
|
static void getfilename(char *line, char *word) ;
|
|
static char * expand_hierarch_keyword(char *, char *) ;
|
|
static int isdetectedkeyword(char *line, char *keywords[], int nkeys) ;
|
|
static void getkeywordvalue(char *line, char *word) ;
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Main
|
|
-----------------------------------------------------------------------------*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char curline[MAX_STRING] ;
|
|
char word[MAX_STRING] ;
|
|
int i, j ;
|
|
int nfiles ;
|
|
record *allrecords ;
|
|
int kwnum ;
|
|
int len ;
|
|
int max_width[MAX_KEY] ;
|
|
int max_filnam ;
|
|
char fmt[8] ;
|
|
int flag ;
|
|
int printnames ;
|
|
int print_hdr ;
|
|
|
|
if (argc<2) {
|
|
printf("\n\nuse : %s [-d] KEY1 KEY2 ... KEYn\n", argv[0]) ;
|
|
printf("Input data is received from stdin\n") ;
|
|
printf("See man page for more details and examples\n\n") ;
|
|
return 0 ;
|
|
}
|
|
|
|
/* Initialize */
|
|
printnames = 0 ;
|
|
print_hdr = 1 ;
|
|
nfiles = 0 ;
|
|
allrecords = (record*)calloc(1, sizeof(record));
|
|
if (!strcmp(argv[1], "-d")) {
|
|
print_hdr = 0;
|
|
argv++ ;
|
|
argc-- ;
|
|
}
|
|
argv++ ;
|
|
|
|
/* Uppercase all inputs */
|
|
for (i=0 ; i<(argc-1) ; i++) {
|
|
j=0 ;
|
|
while (argv[i][j]!=0) {
|
|
argv[i][j] = toupper(argv[i][j]);
|
|
j++ ;
|
|
}
|
|
}
|
|
|
|
while (fgets(curline, MAX_STRING, stdin) != (char*)NULL) {
|
|
flag=isfilename(curline) ;
|
|
if (flag == 1) {
|
|
/* New file name is detected, get the new file name */
|
|
printnames = 1 ;
|
|
getfilename(curline, allrecords[nfiles].filename) ;
|
|
nfiles++ ;
|
|
|
|
/* Initialize a new record structure to store data for this file. */
|
|
allrecords = (record*)realloc(allrecords,(nfiles+1)*sizeof(record));
|
|
for (i=0 ; i<MAX_KEY ; i++) allrecords[nfiles].listkw[i].present=0;
|
|
} else if (flag==0) {
|
|
/* Is not a file name, is it a searched keyword? */
|
|
if ((kwnum = isdetectedkeyword( curline, argv, argc-1)) != -1) {
|
|
/* Is there anything allocated yet to store this? */
|
|
if (nfiles>0) {
|
|
/* It has been detected as a searched keyword. */
|
|
/* Get its value, store it, present flag up */
|
|
getkeywordvalue(curline, word) ;
|
|
strcpy(allrecords[nfiles-1].listkw[kwnum].value, word) ;
|
|
allrecords[nfiles-1].listkw[kwnum].present ++ ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (i=0 ; i<argc-1 ; i++) max_width[i] = (int)strlen(argv[i]) ;
|
|
|
|
/* Record the maximum width for each column */
|
|
max_filnam = 0 ;
|
|
for (i=0 ; i<nfiles ; i++) {
|
|
len = (int)strlen(allrecords[i].filename) ;
|
|
if (len>max_filnam) max_filnam=len ;
|
|
for (kwnum=0 ; kwnum<argc-1 ; kwnum++) {
|
|
if (allrecords[i].listkw[kwnum].present) {
|
|
len = (int)strlen(allrecords[i].listkw[kwnum].value) ;
|
|
} else {
|
|
len = 0 ;
|
|
}
|
|
if (len>max_width[kwnum]) max_width[kwnum] = len ;
|
|
}
|
|
}
|
|
|
|
/* Print out header line */
|
|
if (print_hdr) {
|
|
sprintf(fmt, FMT_STRING, max_filnam) ;
|
|
if (printnames) printf(fmt, "FILE");
|
|
for (i=0 ; i<argc-1 ; i++) {
|
|
sprintf(fmt, FMT_STRING, max_width[i]) ;
|
|
printf(fmt, argv[i]) ;
|
|
}
|
|
printf("\n") ;
|
|
}
|
|
|
|
/* Now print out stored data */
|
|
if (nfiles<1) {
|
|
printf("*** error: no input data corresponding to dfits output\n");
|
|
return -1 ;
|
|
}
|
|
for (i=0 ; i<nfiles ; i++) {
|
|
if (printnames) {
|
|
sprintf(fmt, FMT_STRING, max_filnam) ;
|
|
printf(fmt, allrecords[i].filename) ;
|
|
}
|
|
for (kwnum=0 ; kwnum<argc-1 ; kwnum++) {
|
|
sprintf(fmt, FMT_STRING, max_width[kwnum]);
|
|
if (allrecords[i].listkw[kwnum].present)
|
|
printf(fmt, allrecords[i].listkw[kwnum].value) ;
|
|
else printf(fmt, " ");
|
|
}
|
|
printf("\n") ;
|
|
}
|
|
free(allrecords) ;
|
|
return 0 ;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Functions code
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief find out if an input line contains a file name or a FITS magic nb.
|
|
@param string dfits output line
|
|
@return int (see below)
|
|
Filename recognition is based on 'dfits' output. The function returns 1 if
|
|
the line contains a valid file name as produced by dfits, 2 if it is for an
|
|
extension, 0 otherwise.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static int isfilename(char * string)
|
|
{
|
|
if (!strncmp(string, "====>", 5)) return 1 ;
|
|
if (!strncmp(string, "===>", 4)) return 2 ;
|
|
return 0 ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief returns a file name from a dfits output line
|
|
@param line dfits output line
|
|
@param word file name
|
|
@return a file name from a dfits output line
|
|
This is dfits dependent.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void getfilename(char * line, char * word)
|
|
{
|
|
/* get filename from a dfits output */
|
|
sscanf(line, "%*s %*s %s", word) ;
|
|
return ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief detects a if a keyword is present in a FITS line
|
|
@param line FITS line
|
|
@param keywords set of keywords
|
|
@param nkeys number of kw in the set
|
|
@return keyword rank, -1 if unidentified
|
|
Feed this function a FITS line, a set of keywords in the *argv[] fashion
|
|
(*keywords[]). If the provided line appears to contain one of the keywords
|
|
registered in the list, the rank of the keyword in the list is returned,
|
|
otherwise, -1 is returned.
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static int isdetectedkeyword(
|
|
char * line,
|
|
char * keywords[],
|
|
int nkeys)
|
|
{
|
|
char kw[MAX_STRING] ;
|
|
char esokw[MAX_STRING] ;
|
|
int i ;
|
|
|
|
/* The keyword is up to the equal character, with trailing blanks removed */
|
|
strcpy(kw, line) ;
|
|
strtok(kw, "=") ;
|
|
/* Now remove all trailing blanks (if any) */
|
|
i = (int)strlen(kw) -1 ;
|
|
while (kw[i] == ' ') i -- ;
|
|
kw[i+1] = (char)0 ;
|
|
|
|
/* Now compare what we got with what's available */
|
|
for (i=0 ; i<nkeys ; i++) {
|
|
if (strstr(keywords[i], ".")!=NULL) {
|
|
/*
|
|
* keyword contains a dot, it is a hierarchical keyword that
|
|
* must be expanded. Pattern is:
|
|
* A.B.C... becomes HIERARCH ESO A B C ...
|
|
*/
|
|
expand_hierarch_keyword(keywords[i], esokw) ;
|
|
if (!strcmp(kw, esokw)) {
|
|
return i ;
|
|
}
|
|
} else if (!strcmp(kw, keywords[i])) {
|
|
return i ;
|
|
}
|
|
}
|
|
/* Keyword not found */
|
|
return -1 ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Expand a HIERARCH keyword in format A.B.C to HIERARCH ESO A B C
|
|
@param dotkey Keyword
|
|
@param hierarchy HIERARCH
|
|
@return char *, pointer to second input string (modified)
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static char * expand_hierarch_keyword(
|
|
char * dotkey,
|
|
char * hierarchy)
|
|
{
|
|
char * token ;
|
|
char ws[MAX_STRING] ;
|
|
|
|
sprintf(hierarchy, "HIERARCH ESO");
|
|
strcpy(ws, dotkey) ;
|
|
token = strtok(ws, ".") ;
|
|
while (token!=NULL) {
|
|
strcat(hierarchy, " ") ;
|
|
strcat(hierarchy, token) ;
|
|
token = strtok(NULL, ".");
|
|
}
|
|
return hierarchy ;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**
|
|
@brief Get a keyword value within a FITS line
|
|
@param line FITS line to process
|
|
@param word char string to return result
|
|
@return void, result returned in word
|
|
No complex value is recognized
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static void getkeywordvalue(
|
|
char * line,
|
|
char * word)
|
|
{
|
|
int c, w ;
|
|
char tmp[MAX_STRING] ;
|
|
char *begin, *end ;
|
|
int length ;
|
|
int quote = 0 ;
|
|
int search = 1 ;
|
|
|
|
memset(tmp, (char)0, MAX_STRING) ;
|
|
memset(word, (char)0, MAX_STRING) ;
|
|
c = w = 0;
|
|
|
|
/* Parse the line till the equal '=' sign is found */
|
|
while (line[c] != '=') c++ ;
|
|
c++ ;
|
|
|
|
/* Copy the line till the slash '/' sign or the end of data is found. */
|
|
while (search == 1) {
|
|
if (c>=80) search = 0 ;
|
|
else if ((line[c] == '/') && (quote == 0)) search = 0 ;
|
|
if (line[c] == '\'') quote = !quote ;
|
|
tmp[w++] = line[c++] ;
|
|
}
|
|
|
|
/* NULL termination of the string */
|
|
tmp[--w] = (char)0 ;
|
|
|
|
/* Return the keyword only : a diff is made between text fields and nbs. */
|
|
if ((begin = strchr(tmp, '\'')) != (char*)NULL) {
|
|
/* A quote has been found: it is a string value */
|
|
begin++ ;
|
|
end = strrchr(tmp, '\'') ;
|
|
length = (int)strlen(begin) - (int)strlen(end) ;
|
|
strncpy(word, begin, length) ;
|
|
} else {
|
|
/* No quote, just get the value (only one, no complex supported) */
|
|
sscanf(tmp, "%s", word) ;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|